Streams are append-only log queues designed for multiple independent consumers. Unlike standard queues, messages are not removed when consumed — each consumer maintains its own read position.
Declare a stream by setting x-queue-type: stream:
x-queue-type: stream
Streams are always durable. They cannot be exclusive or auto-delete.
Each consumer can specify where to start reading from using the x-stream-offset argument on basic.consume:
| Value | Description |
|---|---|
first |
Start from the beginning of the stream |
last |
Start from the last available chunk |
next |
Start from new messages only |
| (timestamp) | Start from the first message after the given timestamp |
| (integer) | Start from a specific offset number |
| (negative integer) | Start N messages before the end of the stream (e.g. -100 reads the last 100 messages). Clamped to the oldest available message when fewer than N are stored. 0 retains its meaning of "start from the beginning". |
Delivered messages include an x-stream-offset header with the current offset position.
When no x-stream-offset is specified, the consumer resumes from its last tracked offset (or starts from the beginning if no offset has been stored). If the consumer tag is not auto-generated (does not start with amq.ctag-), future acks also persist new offset positions.
Automatic offset tracking persists the consumer's offset position on the server. It is enabled in two ways:
- Implicitly, when no
x-stream-offsetargument is provided and the consumer tag is not auto-generated (does not start withamq.ctag-) - Explicitly, by setting
x-stream-automatic-offset-tracking: trueonbasic.consumewhen anx-stream-offsetis also specified
On reconnect, the consumer resumes from where it left off without needing to specify the offset manually.
Consumers can filter messages based on headers, avoiding unnecessary delivery of unwanted messages.
Publish messages with the x-stream-filter-value header set to a string value, or a comma-separated list of values to tag a single message with multiple filter values. Consumers set x-stream-filter to match against these values. Only messages whose filter values include the consumer's filter are delivered.
Filter on arbitrary message header key-value pairs. Set x-stream-filter to a table of key-value pairs. Only messages whose headers contain all (or any, depending on match type) of the specified pairs are delivered.
Geospatial filtering allows location-based message delivery. Published messages must include x-geo-lat and x-geo-lon headers with coordinates.
Three filter types are available:
- geo-within-radius — matches messages within a given distance from a point. Specify
lat,lon, andradius_km(in kilometers). - geo-bbox — matches messages within a bounding box. Specify
min_lat,max_lat,min_lon,max_lon. - geo-polygon — matches messages within a polygon. Specify a table with a
pointskey containing an array of[lat, lon]coordinate pairs.
| Argument | Description |
|---|---|
x-stream-filter |
Filter criteria (string, table, or array) |
x-filter-match-type |
all (default) — all filters must match. any — at least one filter must match. |
x-stream-match-unfiltered |
If true, also deliver messages that have no x-stream-filter-value header. This check looks only at x-stream-filter-value, regardless of which filter types are configured. |
Streams support message retention policies to limit storage:
| Mechanism | Description |
|---|---|
x-max-age |
Drop a segment after its last message reaches this age. Format is <number><unit> where unit is one of Y (years), M (months), D (days), h (hours), m (minutes), s (seconds). Units are case-sensitive (e.g., 7D, not 7d). Set as queue argument or max-age policy. |
x-max-length |
Message count retention target. Drop the oldest segment only if at least this many messages remain. Set as queue argument or max-length policy. |
x-max-length-bytes |
Byte retention target. Drop the oldest segment only if at least this many bytes remain. Set as queue argument or max-length-bytes policy. |
Retention removes whole segments, so length limits are not hard maximums. When enough messages have been published, length retention keeps at least the configured target and can exceed it by a segment. For example, a stream with x-max-length: 100 and 1000 messages in one segment keeps that segment until dropping it would still leave at least 100 messages. Length retention is evaluated when a new segment is opened and when its settings change. If several retention limits are configured, another limit can remove messages that one length limit would have kept.
Age retention runs even when no new messages are published. A segment expires based on its last message's timestamp, so earlier messages in that segment may be kept longer than x-max-age. The active write segment is never removed by retention; even if all its messages have expired, it remains until publishing opens a new segment.
| Feature | Standard Queue | Stream |
|---|---|---|
| Message removal | On ack | Never (retention-based) |
| Consumer count | Shared consumption | Independent consumers |
| Acknowledgments | Required for manual ack | Required; persists the per-consumer offset when offset tracking is enabled |
| Requeue | Supported | Supported (in-memory) |
| Exclusive | Supported | Not supported |
| Auto-delete | Supported | Not supported |
| Dead-lettering | Supported | Not supported |
| Priority | Supported | Not supported |
The following arguments are not supported on streams:
x-dead-letter-exchangex-dead-letter-routing-keyx-expiresx-delivery-limitx-overflowx-single-active-consumerx-max-priority