Redis Stream Coordinator
Design docs

Resharding, Routing, and Admin API

Stream Key Model

The coordinator does not append or manage stream-name version tokens. streamPrefix is a user-defined Redis Stream namespace. If an application wants versioned names, it must include that version in streamPrefix itself, for example orders-blue or orders.2026.

The coordinator only appends a shard index:

streamKey = "{streamPrefix}:{shardIndex}"

Examples:

User streamPrefix Shard count Coordinator-created stream keys
orders 3 orders:0, orders:1, orders:2
orders-blue 2 orders-blue:0, orders-blue:1

streamPrefix must not contain Redis Cluster hash tag braces. Shard keys intentionally avoid hash tags so Redis Cluster can distribute them across hash slots.

Producer Routing

Producers never use a local shard count as the source of truth. They fetch routing metadata from the coordinator:

{
  "streamPrefix": "orders",
  "consumerGroup": "orders-consumer",
  "metadataVersion": 12,
  "shardCount": 8,
  "streamKeyPattern": "orders:{shardIndex}"
}

The producer caches this metadata and routes a partition key to a shard index in [0, shardCount). If metadataVersion changes, a cache TTL expires, or a publish detects stale routing, the producer refreshes the cache.

Routing is deterministic only within the same routing metadata snapshot:

If shard count changes, the same partition key can route to a different Redis Stream shard. The coordinator does not globally deduplicate the same event id across every shard.

Duplicate Publish Boundary

Important scenario:

  1. Producer A publishes eventId=E, partitionKey=order-123 with old routing metadata to shard 2.
  2. The Redis response is lost before the producer observes success.
  3. An operator scales the group from 4 shards to 8 shards.
  4. Producer A retries after refreshing routing metadata.
  5. The same partition key can now route to shard 6.
  6. The same event ID can now exist in two shard locations.

Operational constraint:

If producer traffic cannot stop, the workload must be treated as at-least-once and protected by application idempotency.

Resharding Flow

Shard count changes are performed through the Coordinator Admin API.

sequenceDiagram
    participant Admin
    participant C as Coordinator
    participant Store as Metadata Store
    participant Stream as Redis Stream
    participant M as Member

    Admin->>C: Request resharding(targetShardCount)
    C->>Store: Acquire critical section
    C->>Store: Read group metadata
    C->>Store: Validate no active resharding
    C->>Store: Create PREPARING resharding state
    C->>Stream: Provision shard stream keys and consumer groups
    C->>Store: Activate new shard count
    C->>Store: Increment group epoch and recalculate target assignment
    C-->>Admin: Return reshardingId and old/new shard counts
    M->>C: Next heartbeat with current ownership/progress
    C-->>M: Revoke or assign response until target ownership converges

Member Startup Boundary

Member startup is limited to:

Member startup does not:

Admin API Source of Truth

Initial group creation and shard scale-out/in happen only through the Coordinator Admin API.

Source of truth:

Create Group

initialShardCount can be omitted. In that case the coordinator uses configured defaults.

Processing order:

  1. Verify the group does not already exist.
  2. Validate the requested shard count.
  3. Provision shard stream keys and Redis consumer groups when provisioning is enabled.
  4. Store shardCount and groupEpoch=1.
  5. Reject duplicate create requests with 409 Conflict.

Scale Out / Scale In

scale-out and scale-in are represented by the same targetShardCount request.

The coordinator accepts the request only when:

Consumer parallelism is not part of scale metadata. Operators change consumer parallelism by changing the consumer deployment or listener configuration. The coordinator observes the resulting logical members through heartbeat and rebalances by live member count.

Scale-in does not move messages from removed shard streams. Removed shards enter a drain phase:

Monitoring

Group monitoring returns:

Resharding monitoring returns:

Rollback

Rollback is allowed only while the resharding state can be safely reversed by metadata. If messages were already written to newly added shard indexes, they must be drained, replayed, or handled by an operator-defined policy. Rollback does not provide a global transaction across Redis Stream data and coordinator metadata.