kafka · intermediate
Kafka Partition Ordering and Delivery Guarantees
Start here
Apache Kafka is a distributed log: producers append records to topics, topics are split into partitions, and consumers read by advancing offsets.
Two questions dominate real designs:
- Ordering: In what order will consumers see events?
- Delivery: Might an event be lost, duplicated, or processed twice?
- Order is per partition (not global across a topic).
- Consumers usually see at-least-once delivery unless you carefully build stronger guarantees.
- “Exactly-once” marketing language usually means specific producer/broker/consumer configurations plus idempotent side effects—not magic.
What you will learn
- Define topic, partition, offset, and consumer group.
- Explain why keys choose partitions.
- Contrast at-most-once, at-least-once, and practical exactly-once.
- Work a complete order-events example.
- See rebalance and duplicate pitfalls.
- Avoid “Kafka guarantees order” without saying where.
What you should know first
| Topic | Why |
|---|---|
| Message queues | Async delivery vocabulary |
| Pub/sub | Fan-out via consumer groups |
| Idempotency | Duplicates are normal |
Words you need before we begin
| Term | Plain English |
|---|---|
| Topic | Named stream category (for example orders). |
| Partition | Ordered append-only log shard of a topic. |
| Offset | Position of a record inside a partition. |
| Key | Optional field used to pick a partition (and group related events). |
| Consumer group | Set of consumers that share partitions for scale; each record goes to one member. |
| At-least-once | May deliver more than once; tries not to lose. |
| At-most-once | May lose; does not redeliver after certain failures. |
| Idempotent producer | Broker helps avoid duplicate writes for retried produce calls (within limits). |
| Commit offset | Consumer stores “I have processed up to here.” |
| Rebalance | Group membership change that reassigns partitions. |
Simple story: multi-lane post office
A post office has many lanes (partitions). Letters in one lane stay in order. Letters in different lanes can be handled in any interleaving. If a clerk loses their place-marker (offset) and restarts a few letters earlier, some letters get processed twice—unless each letter has a unique id the system ignores on repeat.
Where the analogy stops: Kafka rebalances lanes among clerks automatically and can retain data for days for replay.
The problem without clear guarantees
Team assumes “Kafka is ordered and exactly once.” They process OrderCreated then OrderPaid for many orders on many partitions. Sometimes Paid is handled before Created for the same order because events landed on different partitions or consumers raced. Or a crash after side effect but before offset commit double-charges loyalty points.
Step-by-step explanation
Step 1 — Partition is the ordering unit
Within partition 3, offsets 10, 11, 12 appear in that order to a single-threaded consumer of that partition.
Across partitions 3 and 7, no global order.
Step 2 — Choose keys for entity order
Send all events for orderId=42 with key 42 so they hash to the same partition and preserve per-order order.
Step 3 — Scale with more partitions, not more global order
More partitions → more parallel consumers in a group. Trade-off: harder to get “total order of everything.”
Step 4 — Producer retries and duplicates
Network timeout after broker actually appended can cause retries. Enable idempotent producer for safer produce retries; still design consumers carefully.
Step 5 — Consumer commit timing defines delivery
- Commit before processing → risk at-most-once (loss on crash).
- Process then commit → at-least-once (duplicate on crash after process, before commit).
Step 6 — Rebalances interrupt
On rebalance, another consumer may resume near the last committed offset—duplicates possible.
Step 7 — Stronger processing needs more pieces
Transactional producers, exactly-once consumer semantics (read-process-write with Kafka transactions), and idempotent external side effects. Treat as advanced; do not claim casually.
Visual mental model
flowchart TB
P[Producer] -->|key=order-42| T[Topic orders]
T --> P0[Partition 0]
T --> P1[Partition 1]
T --> P2[Partition 2]
P1 --> C[Consumer in group G]
C -->|commit offset| O[(Offsets)]
Learning question: If OrderCreated and OrderPaid use different keys, can a consumer see Paid first?
Caption: Yes—different partitions destroy per-order ordering.
Complete worked example: order lifecycle stream
Starting situation
Services publish OrderCreated, PaymentCaptured, OrderShipped for millions of orders per day. Loyalty service awards points once per paid order.
Constraints
- Per-order event order required
- Loyalty must not double-award on redelivery
- Three consumers in one group for throughput
Decisions
| Item | Choice |
|---|---|
| Topic | order-lifecycle with 24 partitions |
| Key | orderId for all events |
| Producer | acks=all, idempotence enabled |
| Consumer | process then commit; max poll records bounded |
| Loyalty | DB unique constraint on orderId award |
Failure behavior
- Crash after award before commit: redelivery; unique constraint no-ops second award.
- Wrong key null: events spread randomly; order breaks—alert on null keys.
- Rebalance mid-batch: duplicates; idempotency saves.
Outcome
Ordered per order, scalable across orders. Limitation: no single global timeline of all orders without a different design.
How it works in production
- Monitor consumer lag per partition
- Alert on stuck consumers and growing lag
- Schema registry for payloads
- Runbooks for poison messages and offset resets (dangerous)
Failure modes
| Mode | Impact | Mitigation |
|---|---|---|
| Null keys | Lost entity order | Require keys; reject null |
| Commit before process | Lost effects | Prefer process-then-commit |
| Non-idempotent handler | Double side effects | Dedupe store / unique keys |
| Too few partitions | Throughput ceiling | Plan partitions early (hard to change casually) |
| Offset reset to earliest | Mass reprocessing | ACL + careful ops |
| Assuming EOS everywhere | False safety | Document actual guarantee |
Trade-offs
| Choice | Benefit | Cost |
|---|---|---|
| Many partitions | Parallelism | Harder ops, more files |
| Single partition | Total order | No scale |
| At-least-once | Durability of intent | Duplicates |
| Stricter EOS setups | Stronger pipeline guarantees | Complexity, limitations |
Compare with related concepts
| Concept | Difference |
|---|---|
| Classic queue | Competing consumers; different ops model |
| Pub/sub fan-out | Multiple groups each read full stream |
| DB transactions | Single-system ACID; Kafka is a log |
| Exactly-once lesson | Deeper transactional API details |
Common misunderstandings
- “Kafka is always globally ordered.” Only per partition.
- “At-least-once means no duplicates.” It means the opposite risk.
- “Idempotent producer equals exactly-once business effects.” External side effects still need care.
- “More consumers than partitions helps.” Extra consumers in a group sit idle.
- “Replaying a topic is free.” Side effects may not be.
Check your understanding
- Where does Kafka guarantee order?
- Why use
orderIdas key? - What delivery mode is process-then-commit?
- What happens if consumers exceed partition count in a group?
- How do you prevent double loyalty awards?
Practice
- Design keys for multi-tenant events where order is per tenant.
- Sketch consumer lag alerts for a payments topic.
- Explain a duplicate after rebalance with a timeline.
- Choose partition count for 50 MB/s with rough math.
- List what “exactly-once” would require beyond defaults.
Deeper production notes
Head-of-line and slow keys
A hot key can overload one partition. Watch produce/consume imbalance. Design keys for both order and cardinality.
Poison records
Deserialization failures can block a partition consumer loop if not handled. Use dead-letter patterns and skip policies carefully.
Specialist caution
Kafka transactions and EOS configurations evolve by version. Verify against current Apache Kafka docs before promising regulatory-grade guarantees.
Additional teaching scenarios
Scenario A — peak load day
Traffic multiplies by ten. Re-read the failure modes and mark which appear first. Write the first mitigation for each.Scenario B — mixed versions
Half the fleet runs the old build. Which assumptions break if protocols or schemas disagree? Prefer designs that tolerate one deploy window of mixed versions.Scenario C — five-sentence teach-back
Explain the core idea without acronyms. If you cannot, revisit the simple story and worked example.Scenario D — metrics and alerts
List three metrics and one alert threshold that name user impact or a resource that runs out.Scenario E — non-goals
Write two problems this technique should **not** solve, to prevent cargo-cult adoption.Scenario F — ownership
Name who owns dashboards, code changes, and pages. Blank ownership means the feature is not ready for broad enablement.Revision summary
- Order is per partition; use keys for entity order.
- Default consumer reality is at-least-once.
- Build idempotent side effects.
- Scale with partitions; do not invent global order casually.
- Treat “exactly-once” as an advanced, partial property—not a slogan.
Glossary
| Term | Definition |
|---|---|
| Partition | Ordered log shard of a topic. |
| Offset | Record position in a partition. |
| Consumer group | Cooperative consumers sharing partitions. |
| At-least-once | Delivery that prioritizes not losing records. |
Abbreviations and terminology
- EOS — Exactly-once semantics (context-specific)
- ISR — In-sync replicas (broker durability topic)
- ack — Producer acknowledgment setting
What to learn next
- Kafka architecture deep dive
- Kafka exactly-once semantics
- Idempotency, retries, backoff
- Dead-letter queues
Extra teaching notes for first-time builders
Write the single bottleneck you are protecting before picking tools. Name the signal that tells you the design is working for users, not only that internal counters move. When reviewing a change related to this lesson, ask what happens when the component is slow for ten minutes, down entirely, or running twice. Prefer small explicit failure modes that operators can understand at 3 a.m.
Document ownership for dashboards, code, and pages. Undocumented mechanisms become folklore and then outages. Prefer designs that tolerate mixed versions for at least one deploy window so rollouts do not require perfect global simultaneity.
Napkin math helps: estimate peak rate, multiply by payload size, and ask whether the design still holds when a dependency is at half capacity. If the answer depends on luck, add bounds, backpressure, or shedding before production traffic arrives.
FAQ from first-time learners
Q: Can I get global order with one partition?
A: Yes for that topic, at the cost of throughput.
Q: Do multiple consumer groups each see all messages?
A: Yes—each group has its own offsets (pub/sub style fan-out).
Q: Is Kafka a database?
A: It is a durable log. Some patterns use it as a source of truth, but it is not a general relational store.
Track: Data, Storage and Messaging
Previous: Kafka Exactly-Once Semantics — What Is Actually Guaranteed
Next: Kafka Streams Introduction
Series: Kafka & Event Streaming
- Message Queues — Hand Work Off Without Blocking the User
- Kafka Architecture — Brokers, Partitions, ISR, and Consumers
- Kafka Partition Ordering and Delivery Guarantees (this guide)
- Kafka Exactly-Once Semantics — What Is Actually Guaranteed
- Transactional Outbox and Saga Patterns — Reliable Multi-Step Work
- Kafka Streams Introduction
- Kafka with Spring Boot Code Walkthrough
By Shubham Jain