> ## Documentation Index
> Fetch the complete documentation index at: https://upstash.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# XACKDEL

> Acknowledge and delete stream entries atomically.

The `XACKDEL` command acknowledges and deletes stream entries atomically in a single operation. This is useful for consumer groups where you want to acknowledge message processing and remove the entries from the stream simultaneously.

## Arguments

<ParamField body="key" type="string" required>
  The key of the stream.
</ParamField>

<ParamField body="group" type="string" required>
  The consumer group name.
</ParamField>

<ParamField body="option" type="'KEEPREF' | 'keepref' | 'DELREF' | 'delref' | 'ACKED' | 'acked'">
  Optional deletion behavior (case-insensitive). When provided, must come before the IDs:

  * `KEEPREF`: Keep consumer group references
  * `DELREF`: Delete consumer group references
  * `ACKED`: Only acknowledge messages (don't delete)

  If not provided, entries are acknowledged and deleted by default.
</ParamField>

<ParamField body="ids" type="...string[]" required>
  One or more stream entry IDs to acknowledge and delete. When an option is provided, IDs must come after the option.
</ParamField>

## Response

<ResponseField type="any[]" required>
  An array indicating the result for each ID in the same order as provided.
</ResponseField>

<RequestExample>
  ```ts Single Entry theme={"system"}
  // Acknowledge and delete a single entry
  const result = await redis.xackdel("mystream", "mygroup", "1638360173533-0");
  console.log(result); // Array of results for each ID
  ```

  ```ts Multiple Entries theme={"system"}
  // Acknowledge and delete multiple entries
  const result = await redis.xackdel(
    "mystream", 
    "mygroup",
    "1638360173533-0",
    "1638360173533-1",
    "1638360173533-2"
  );
  console.log(result); // Array of results for each ID
  ```

  ```ts With KEEPREF Option theme={"system"}
  // Keep consumer group references when deleting entries
  // Useful when you want to delete entries but maintain group tracking
  const result = await redis.xackdel(
    "mystream",
    "mygroup",
    "KEEPREF",
    "1638360173533-0",
    "1638360173533-1",
  );
  console.log(result); // Array of results for each ID
  ```

  ```ts With DELREF Option theme={"system"}
  // Delete consumer group references along with entries
  // Useful for complete cleanup of processed messages
  const result = await redis.xackdel(
    "mystream",
    "mygroup",
    "DELREF",
    "1638360173533-0",
    "1638360173533-1",
  );
  console.log(result); // Array of results for each ID
  ```

  ```ts With ACKED Option theme={"system"}
  // Only acknowledge messages without deleting them
  // Useful when you want to mark as processed but keep for audit/debugging
  const result = await redis.xackdel(
    "mystream",
    "mygroup",
    "ACKED",
    "1638360173533-0",
  );
  console.log(result); // Array of results for each ID
  // Entry remains in stream but is acknowledged
  ```

  ```ts Consumer Group Processing theme={"system"}
  // Create a consumer group
  await redis.xgroup("CREATE", "orders", "processors", "0", "MKSTREAM");

  // Add some orders to the stream
  await redis.xadd("orders", "*", { order_id: "123", status: "pending" });
  await redis.xadd("orders", "*", { order_id: "124", status: "pending" });

  // Read messages as a consumer
  const messages = await redis.xreadgroup(
    "GROUP", "processors", "consumer1",
    "COUNT", 2,
    "STREAMS", "orders", ">"
  );

  // Process messages and acknowledge + delete them
  for (const [stream, entries] of messages) {
    for (const [id, fields] of entries) {
      // Process the order...
      console.log(`Processing order ${fields.order_id}`);
      
      // Acknowledge and delete the entry (default behavior)
      await redis.xackdel("orders", "processors", id);
      
      // Or use DELREF for complete cleanup
      // await redis.xackdel("orders", "processors", "DELREF", id);
    }
  }
  ```

  ```ts Batch Processing theme={"system"}
  // Read pending messages
  const pending = await redis.xreadgroup(
    "GROUP", "tasks", "worker1",
    "COUNT", 10,
    "STREAMS", "task-queue", ">"
  );

  if (pending && pending.length > 0) {
    const [stream, entries] = pending[0];
    const processedIds: string[] = [];
    
    // Process each task
    for (const [id, fields] of entries) {
      try {
        // Process task...
        console.log(`Processing task ${id}`);
        processedIds.push(id);
      } catch (error) {
        console.error(`Failed to process ${id}:`, error);
      }
    }
    
    // Acknowledge and delete all successfully processed tasks
    // Using DELREF to completely remove references
    if (processedIds.length > 0) {
      const result = await redis.xackdel("task-queue", "tasks", "DELREF", ...processedIds);
      console.log(`Results: ${result}`); // Array of results for each ID
    }
  }
  ```

  ```ts Audit Mode with ACKED theme={"system"}
  // Process messages but keep them for audit/debugging purposes
  const messages = await redis.xreadgroup(
    "GROUP", "audit", "auditor1",
    "COUNT", 5,
    "STREAMS", "events", ">"
  );

  for (const [stream, entries] of messages) {
    const entryIds = entries.map(([id]) => id);
    
    // Process and acknowledge but don't delete
    for (const [id, fields] of entries) {
      // Audit the event...
      console.log(`Auditing event ${JSON.stringify(fields)}`);
    }
    
    // Acknowledge without deleting (keep for audit trail)
    const result = await redis.xackdel("events", "audit", "ACKED", ...entryIds);
    console.log(`Acknowledged ${result.length} events (kept in stream)`);
  }
  ```
</RequestExample>

## Use Cases

* **Message Queue Cleanup**: Process messages and remove them from the stream in one operation
* **Event Processing**: Acknowledge event handling and clean up the stream
* **Task Queue Management**: Complete tasks and remove them atomically
* **Memory Optimization**: Reduce stream memory usage by removing processed entries

## Comparison with XACK + XDEL

Traditional approach (two operations):

```ts theme={"system"}
// Acknowledge the message
await redis.xack("mystream", "mygroup", "123-0");
// Then delete it
await redis.xdel("mystream", "123-0");
```

With XACKDEL (single atomic operation):

```ts theme={"system"}
// Acknowledge and delete in one operation (default)
await redis.xackdel("mystream", "mygroup", "123-0");

// With options for fine-grained control
await redis.xackdel("mystream", "mygroup", "DELREF", "123-0"); // Complete cleanup
await redis.xackdel("mystream", "mygroup", "ACKED", "123-0");  // Acknowledge only
```

<Note>
  This command is available in Redis 8.2.0 and later. It combines XACK and XDEL into a single atomic operation, which is more efficient and ensures consistency.
</Note>
