XNACK

XNACK key group <SILENT | FAIL | FATAL> IDS numids id [id ...]
  [RETRYCOUNT count] [FORCE]
Available since:
Redis Open Source 8.8.0
Time complexity:
O(1) for each message ID processed.
ACL categories:
@stream,
Compatibility:
Redis Software and Redis Cloud compatibility

In the context of a stream consumer group, this command allows a consumer to explicitly release pending messages back to the group's Pending Entries List (PEL) without acknowledging them. Released messages become immediately available for re-delivery to other consumers in the group, eliminating the idle-timeout delay normally required for message recovery.

This is particularly useful in scenarios such as graceful consumer shutdown, consumer-side failures, resource constraints, or poison message detection. The command provides three different modes that control how the delivery counter is adjusted, giving consumers fine-grained control over retry semantics.

Required arguments

key

Name of the stream.

group

Name of the consumer group.

mode

Controls the delivery counter adjustment. Must be one of:

  • SILENT: Decrements the delivery counter by 1, essentially "undoing" the delivery increment. Use this for an internal failure on the consumer side while processing the message or graceful shutdown where the delivery "didn't count".
  • FAIL: Keeps the current delivery counter value unchanged. Use this when the current consumer failed to process this message (for example, due to memory constraints). The root cause may be the message or the consumer (it is unclear), so the best strategy would be to let another consumer try to process the message.
  • FATAL: Sets the delivery counter to the maximum value (LLONG_MAX or ~9.22 X 1018), marking the message as permanently failed. Use this for invalid or suspected malicious messages.
ids

Block of arguments that specifies the message IDs to release, where numids is the number of message IDs that follow, and id [id ...] represents the stream entry IDs to be released back to the group.

Optional arguments

RETRYCOUNT

Directly sets the delivery counter to the specified value, overriding the mode-based adjustment. This gives explicit control over the retry counter regardless of the mode selected. Note: this is an internal argument that should usually not be used by consumers.

FORCE

Creates new unowned PEL entries for IDs that are not already in the group PEL. Each entry must exist in the stream. When FORCE creates an entry, the delivery counter is set to 0 (or to RETRYCOUNT if specified, or to LLONG_MAX if mode is FATAL). Note: this is an internal argument that should usually not be used by consumers.

Examples

Basic usage with FAIL mode
> XADD mystream * field value1
"1526569498055-0"
> XADD mystream * field value2
"1526569498056-0"
> XGROUP CREATE mystream mygroup 0
OK
> XREADGROUP GROUP mygroup consumer1 STREAMS mystream >
1) 1) "mystream"
   2) 1) 1) "1526569498055-0"
         2) 1) "field"
            2) "value1"
      2) 1) "1526569498056-0"
         2) 1) "field"
            2) "value2"
> XNACK mystream mygroup FAIL IDS 2 1526569498055-0 1526569498056-0
(integer) 2

After NACKing, the messages appear with empty consumer in XPENDING:

> XPENDING mystream mygroup - + 10
1) 1) "1526569498055-0"
   2) ""
   3) (integer) -1
   4) (integer) 1
2) 1) "1526569498056-0"
   2) ""
   3) (integer) -1
   4) (integer) 1
Using SILENT mode for graceful shutdown
> XNACK mystream mygroup SILENT IDS 1 1526569498055-0
(integer) 1

With SILENT mode, the delivery counter is decremented, effectively "undoing" the delivery.

Using FATAL mode for poison messages
> XNACK mystream mygroup FATAL IDS 1 1526569498055-0
(integer) 1

This marks the message as permanently failed by setting the delivery counter to maximum value.

Behavior

When XNACK executes successfully, the entry:

  • is marked as unowned (its last consumer is set to an empty string).
  • is assigned a last delivery time of 0.
  • is placed at the end of the NACKed portion of the PEL.
  • is available for immediate re-delivery via XREADGROUP CLAIM, XCLAIM, or XAUTOCLAIM.

The head of the PEL is reserved for all NACKed messages, ordered as a FIFO list, followed by pending messages that were neither ACKed nor NACKed in their existing order.

NACKed messages are prioritized over other pending messages in the group's PEL, ensuring they are delivered before idle messages during claim operations.

Notes

  • XNACK will only process message IDs that exist in the consumer group's PEL. Messages that are not pending will be ignored and not counted in the return value.
  • Released messages occupy a dedicated zone at the head of the PEL (called the XNACKed portion of the PEL), ensuring they are prioritized for re-delivery over other pending entries.
  • Released messages have their delivery time set to 0, making them immediately claimable regardless of the min-idle-time parameter in claiming commands.
  • Unlike XACK, this command does not remove messages from the PEL but instead makes them available for other consumers.

Redis Software and Redis Cloud compatibility

Redis
Software
Redis
Cloud
Notes
❌ Standard
❌ Active-Active
❌ Standard
❌ Active-Active

Return information

Integer reply: The number of messages successfully released back to the group PEL. Messages that are not in the consumer group PEL will not be counted.

See also

  • XREADGROUP: Read messages from a consumer group
  • XACK: Acknowledge processed messages
  • XCLAIM: Claim pending messages from other consumers
  • XAUTOCLAIM: Automatically claim idle pending messages
  • XPENDING: Inspect pending messages in a consumer group
RATE THIS PAGE
Back to top ↑