Exclusive
One consumer per subscription. Guarantees strict message ordering.
- Ordered delivery
- No horizontal scaling
- Use case: sequential workflows
A subscription is a named rule that determines how messages from a topic are delivered to consumers. Danube supports multiple producers and subscribers on the same topic, and subscription types can be combined to build queuing or fan-out messaging patterns.
Exclusive
One consumer per subscription. Guarantees strict message ordering.
Shared
Multiple consumers, round-robin delivery. Scales horizontally.
Failover
One active consumer with standby. Automatic failover preserves ordering.
Key-Shared
Multiple consumers, routed by key. Per-key ordering with horizontal scaling.
Only one consumer can attach to the subscription. If a second consumer tries to subscribe with the same name, it receives an error. The single consumer receives all messages in order.
One consumer handles all messages from the topic.
One consumer handles messages from all partitions of the topic.
Multiple consumers attach to the same subscription. Messages are delivered round-robin across consumers, and each message goes to exactly one consumer.
Messages are distributed among all consumers in round-robin fashion.
Messages from all partitions are distributed round-robin across all consumers. Each message from any partition goes to exactly one consumer.
Multiple consumers attach, but only one is active at a time. If the active consumer disconnects, another consumer takes over automatically. This preserves ordering while providing high availability.
One active consumer processes all messages. Additional consumers are on standby.
One active consumer per partition. Other consumers remain on standby for each partition. Failover occurs independently per partition.
Multiple consumers attach to the same subscription, where each message is routed based on its routing key. All messages with the same key go to the same consumer, in order.
This combines the parallelism of Shared subscriptions with per-key ordering guarantees.
Consumers can declare key filter patterns to receive only specific subsets of messages. Filters use glob syntax:
| Pattern | Matches |
|---|---|
"payment" | Exact match only |
"ship*" | "shipping", "shipment", etc. |
"eu-west-?" | "eu-west-1", "eu-west-2", etc. |
"*" | Everything (same as no filter) |
If a consumer has no filters, it accepts all keys. If a message’s routing key matches no consumer’s filters, the message is skipped by that subscription.
Producers tag messages with a routing key using send_with_key():
// All "payment" messages go to the same consumerproducer.send_with_key(data, None, "payment").await?;producer.send_with_key(data, None, "shipping").await?;If a message is sent without a routing key (using send()), the producer name is used as the fallback key.
// Automatic key distribution — no filterslet mut consumer = client .new_consumer() .with_topic("/default/orders") .with_consumer_name("worker_1") .with_subscription("orders_sub") .with_subscription_type(SubType::KeyShared) .build()?;
// Explicit key filtering — only receive matching keyslet mut consumer = client .new_consumer() .with_topic("/default/orders") .with_consumer_name("payments_worker") .with_subscription("orders_sub") .with_subscription_type(SubType::KeyShared) .with_key_filter("payment") .with_key_filter("invoice") .build()?;Subscription types map directly to common messaging patterns.
One message is delivered to exactly one consumer in a group. Use a Shared subscription with the same name across all workers:
/default/ordersorders-workers (type Shared)Every downstream service receives every message. Create a separate subscription per service:
/default/eventsbilling (Exclusive), analytics (Exclusive), monitoring (Failover)Messages with the same key must be processed by the same consumer for ordering or state consistency. Use a Key-Shared subscription:
/default/ordersorder-processors (type KeyShared)All subscription patterns work with either dispatch mode:
See Dispatch Strategies for details.