Understanding Pulsar’s subscription types and consumption patterns
Subscriptions are named configurations that track message consumption progress for one or more consumers. Pulsar supports multiple subscription types, each with different semantics.
Subscriptions are durable - even if all consumers disconnect, the subscription cursor position is preserved. When consumers reconnect, they resume from where they left off.
Multiple consumers can attach, but only one actively receives messages.
public enum SubscriptionType { /** * Multiple consumers can use the same subscription name but only 1 consumer * will receive messages. If that consumer disconnects, one of the other * connected consumers will start receiving messages. * * In failover mode, the consumption ordering is guaranteed. * * In case of partitioned topics, the ordering is guaranteed on a per-partition basis. * The partition assignments will be split across available consumers. */ Failover}
Multiple consumers receive messages in round-robin distribution.
public enum SubscriptionType { /** * Multiple consumers will be able to use the same subscription name and * messages will be dispatched according to a round-robin rotation between * connected consumers. * * In this mode, the consumption order is not guaranteed. */ Shared}
Messages with the same key go to the same consumer.
public enum SubscriptionType { /** * Multiple consumers can use the same subscription and all messages with * the same key will be dispatched to only one consumer. * * Use ordering_key to overwrite the message key for message ordering. */ Key_Shared}
Consumer<String> consumer = client.newConsumer(Schema.STRING) .topic("my-topic") .subscriptionName("my-key-shared-sub") .subscriptionType(SubscriptionType.Key_Shared) .subscribe();// Producer sends messages with keysproducer.newMessage() .key("user-123") // All messages with this key go to same consumer .value("order data") .send();
Characteristics:
Ordering guaranteed per key
Parallel processing across different keys
Keys distributed across consumers using hash
Can use orderingKey instead of message key
Use Cases:
Per-entity ordering (e.g., per-user, per-device)
Stateful processing where related messages must be processed together
Combining parallelism with partial ordering
Messages without a key are distributed round-robin. Always set keys for messages when using Key_Shared subscriptions.
Message<String> msg = consumer.receive();processMessage(msg);consumer.acknowledgeCumulative(msg);// All messages up to and including 'msg' are acknowledged
Cumulative acknowledgment is not supported with Shared or Key_Shared subscriptions because message ordering is not guaranteed.
Messages<String> messages = consumer.batchReceive();for (Message<String> msg : messages) { processMessage(msg);}consumer.acknowledge(messages); // Acknowledge all at once