Kafka Delivery Semantics
When a producer sends a message, how sure can it be that the message was stored? When a consumer reads a message, how do you prevent duplicates or losses? These are Kafka's delivery semantics -- and getting them right is one of the hardest problems in distributed messaging.
Producer delivery guarantees
The producer controls durability via the acks (acknowledgment) setting:
| Setting | What happens | Durability | Performance |
|---|---|---|---|
| acks=0 (fire-and-forget) | Producer sends and doesn't wait for any confirmation | Lowest -- message could be lost | Fastest -- network speed |
| acks=1 (leader only) | Producer waits for the leader to confirm | Medium -- lost if leader crashes before replication | Fast |
| acks=all (leader + ISR) | Producer waits for the leader and all ISRs to confirm | Highest -- survives any single broker failure | Slowest |
acks=0 is for fire-and-forget telemetry. acks=1 is the common default. acks=all is for data you absolutely cannot lose (financial transactions, order events). Always match the ack level to the business value of the data.
Consumer delivery guarantees
The consumer side is about the relationship between processing a message and committing the offset:
| Guarantee | How it works | Risk |
|---|---|---|
| At-most-once | Commit offset before processing. If the consumer crashes mid-processing, the message is skipped. | Message loss |
| At-least-once | Commit offset after processing. If the consumer crashes after processing but before committing, the message is reprocessed. | Duplicate processing |
| Exactly-once | Processing and offset commit happen in a single transaction. If the consumer crashes, the transaction rolls back and the message is reprocessed cleanly. | None (but lower throughput) |
Exactly-once: how it actually works
Exactly-once requires three mechanisms working together:
- Idempotent producers: Each message gets a sequence number. The broker deduplicates based on (producer ID, sequence number).
- Transactional writes: Producers can atomically write to multiple partitions and commit offsets in a single transaction.
- Transactional consumers: Consumers configured to read only committed messages (
isolation.level=read_committed).
"How does Kafka achieve exactly-once delivery?" is a common interview question. The answer: idempotent producers (sequence number dedup on the broker), transactions (atomic writes across partitions), and read_committed consumers. Note that exactly-once is end-to-end only if the consumer's side effects are also idempotent or part of the transaction.