Redis Stream ReadGroup

Redis Stream ReadGroup

Certified

Read entries from a Redis stream consumer group

Runs one bounded XREADGROUP for the given consumer and returns each entry with its stream name, its exact stream ID and its field-value map. Field names and values are returned exactly as Redis stores them, with no serialization format applied, so an ID can be fed straight back into Ack.

The read is bounded on both axes. count caps how many entries a single call delivers, and blockDuration caps how long the call waits when the group has nothing to deliver; leaving blockDuration unset makes the call return immediately, and it cannot exceed one hour. XREADGROUP BLOCK 0, which waits forever, is deliberately not reachable. Killing the task closes the connection, so a waiting read stops instead of holding a worker thread.

Delivery is at-least-once. Every entry this task returns is added to the group's Pending Entries List for this consumer and stays there until Ack removes it, so a flow that fails after the read leaves the entry pending and a later run can pick it up again. The consumer name is therefore part of the contract: entries delivered to one consumer name remain owned by that name. Use a stable name per worker role, keep processing idempotent because a crash between a business write and the acknowledgement replays the entry, and set offset to 0 to re-read this consumer's own unacknowledged entries instead of new ones.

yaml
type: io.kestra.plugin.redis.stream.ReadGroup

Read, process and acknowledge entries from a stream consumer group.

yaml
id: redis_stream_consume
namespace: company.team

tasks:
  - id: create_group
    type: io.kestra.plugin.redis.stream.GroupCreate
    url: "{{ secret('REDIS_URI') }}"
    key: orders
    group: billing
    startId: "0"

  - id: read
    type: io.kestra.plugin.redis.stream.ReadGroup
    url: "{{ secret('REDIS_URI') }}"
    key: orders
    group: billing
    consumer: billing_worker_1
    count: 10
    blockDuration: PT5S

  - id: process
    type: io.kestra.plugin.core.log.Log
    message: "handling {{ outputs.read.count }} entries: {{ outputs.read.messages }}"

  - id: acknowledge
    type: io.kestra.plugin.redis.stream.Ack
    url: "{{ secret('REDIS_URI') }}"
    key: orders
    group: billing
    ids: "{{ outputs.read.ids }}"
    runIf: "{{ outputs.read.count > 0 }}"

Recover this consumer's own entries that were read but never acknowledged.

yaml
id: redis_stream_recover_own
namespace: company.team

tasks:
  - id: read_pending
    type: io.kestra.plugin.redis.stream.ReadGroup
    url: "{{ secret('REDIS_URI') }}"
    key: orders
    group: billing
    consumer: billing_worker_1
    offset: "0"
    count: 100

Store a batch in Kestra internal storage instead of returning it inline.

yaml
id: redis_stream_store
namespace: company.team

tasks:
  - id: read
    type: io.kestra.plugin.redis.stream.ReadGroup
    url: "{{ secret('REDIS_URI') }}"
    key: orders
    group: billing
    consumer: billing_worker_1
    fetchType: STORE
    count: 500
Properties

Consumer name inside the group

Rendered consumer name. Redis tracks pending entries per consumer, so entries delivered under this name stay owned by it until they are acknowledged. Use a stable name per worker role rather than a value that changes on every execution, otherwise unacknowledged entries are stranded under a name nothing reads again.

Consumer group name

Rendered group name; the group must already exist, so create it with GroupCreate first. Reading from a missing group fails with NOGROUP.

Redis stream key

Rendered key passed to XREADGROUP.

Redis connection string

Assets this task consumes as inputs or produces as outputs, for lineage tracking and the asset graph (Enterprise Edition). A flow declaring this property on a task is rejected in the open-source edition.

Definitions
assetFailureBehaviorstring
Possible Values
IGNOREFAILWARN

Asset failure behavior

Behavior applied to the task state when a declared asset fails to render, emit, or be persisted (e.g. a lock conflict): FAIL escalates it to FAILED, WARN (default) warns it if it would otherwise succeed, IGNORE leaves the state untouched.

enableAutobooleanstring

Whether to auto-register assets referenced dynamically at runtime that are not statically declared in inputs or outputs.

inputsarray

The assets consumed as inputs.

id*string
Min length1
typestring
outputs

The assets produced as outputs.

id*string
Min length1
Max length150
type*object
descriptionstring
displayNamestring
metadataobject
Default{}
namespacestring
Min length1
Max length150
id*string
Min length1
Max length150
type*object
descriptionstring
displayNamestring
metadataobject
Default{}
namespacestring
Min length1
Max length150
id*string
Min length1
Max length150
type*object
descriptionstring
displayNamestring
metadataobject
Default{}
namespacestring
Min length1
Max length150
id*string
Min length1
Max length150
type*object
descriptionstring
displayNamestring
metadataobject
Default{}
namespacestring
Min length1
Max length150
id*string
Min length1
Max length150
type*object
descriptionstring
displayNamestring
metadataobject
Default{}
namespacestring
Min length1
Max length150
id*string
Min length1
Max length150
type*string
Min length1

Custom asset type

descriptionstring
displayNamestring
metadataobject
Default{}
namespacestring
Min length1
Max length150

How long to wait for entries

Maps to BLOCK. Unset by default, which makes the read return immediately with whatever is available. When set it must be strictly positive and at most 1 hour (PT1H); BLOCK 0, which waits forever, is not supported because the read has to stay bounded. The client command timeout is raised above this value for the call. The task-level timeout can cap the wait further.

Default100

Maximum entries per read

Defaults to 100 and maps to COUNT. Must be between 1 and 10000. Forced to 1 when fetchType is FETCH_ONE, so the task never makes Redis mark entries as delivered that the flow cannot see or acknowledge.

DefaultFETCH
Possible Values
STOREFETCHFETCH_ONENONE

How entries are returned

Defaults to FETCH, which returns every entry of the batch in messages. FETCH_ONE returns a single entry in message and forces count to 1. STORE writes the batch as an ION file to Kestra internal storage and returns its uri. NONE returns no entry body; count and ids are still populated, so the batch can be acknowledged or counted without carrying the payload.

Defaultfalse

Skip the pending list for this read

Defaults to false. When true the read adds NOACK, so Redis never records the entries as pending and Ack has nothing to remove. This downgrades delivery to at-most-once: an entry lost by a failing flow is not redelivered. Leave it false whenever the work must not be lost.

Default>

Stream ID to read from

Defaults to >, which delivers entries never handed to any consumer of the group and adds them to this consumer's pending list. Use 0 to re-read this consumer's own already delivered but unacknowledged entries, oldest first, or any explicit stream ID to re-read its pending entries after that ID. Only > delivers new entries.

Consumer name the entries are now pending for

Number of entries delivered by this read

Consumer group that was read

SubTypestring

Exact stream IDs delivered by this read

In delivery order, ready to be passed to Ack. Populated for every fetchType.

Single entry delivered by this read

Only set when fetchType is FETCH_ONE; null when the read returned nothing.

Definitions
fieldsobject
SubTypestring

Field-value map of the entry

Returned exactly as stored in Redis, with no serialization format applied.

idstring

Exact stream ID of the entry

Pass it to Ack to remove the entry from the group's pending list.

streamstring

Stream the entry was read from

Entries delivered by this read

Only set when fetchType is FETCH.

Definitions
fieldsobject
SubTypestring

Field-value map of the entry

Returned exactly as stored in Redis, with no serialization format applied.

idstring

Exact stream ID of the entry

Pass it to Ack to remove the entry from the group's pending list.

streamstring

Stream the entry was read from

Stream that was read

Formaturi

URI of the ION file holding the entries

Only set when fetchType is STORE.

Unitrecords

Number of entries delivered by XREADGROUP.