Monedula

Kafka troubleshooting

Messages arrive out of order

Kafka symptom

Kafka guarantees order only within a partition: a consumer reads each partition in the order its records were written, and there is no order across partitions. Messages arrive out of order when related records land in different partitions, when the partition count changes, when a non-idempotent producer retries with more than one request in flight, or when the consumer processes records in parallel.

Reproduce it in the playground

The moment it happensA's retry lands at offset 2 - REORDER. t+3.600s

A's retry finally appends at offset 2. The log is [A, B, A]: A was produced before B, yet its retried copy sits AFTER B. max.in.flight > 1 + idempotence off reordered the log (and, being non-idempotent, also duplicated A).

Open at this step: step 5, A's retry lands at offset 2 - REORDER

What it means

The default partitioner sends records with the same key to the same partition, which is how per-key order survives on a topic with many partitions. Records without a key are spread across partitions batch by batch, so two of them can be read in either order. Within a partition, the producer may keep up to max.in.flight.requests.per.connection unacknowledged requests on a connection (5 by default). With the idempotent producer, on by default since Kafka 3.0, the broker uses sequence numbers to keep those batches in order for any allowed value. With idempotence off and retries on, a batch that fails and is retried can land after a batch that was sent later. The producer logs every such retry, for example "Got error produce response with correlation id 7 on topic-partition orders-0, retrying (2147483646 attempts left). Error: NETWORK_EXCEPTION. Error Message: Disconnected from node 1", so that warning on a producer with enable.idempotence=false and more than one request in flight is the sign to look for.

Likely causes, most common first

  1. Related records have different keys, or none. The order between, say, an order-created and an order-paid event only holds if both carry the same key. Keyless records, or a key that differs between event types, put them in different partitions, and partitions are read independently.
  2. The partition count changed. The default partitioner maps a key to a partition by its hash and the partition count, so adding partitions moves keys to different partitions. New records for a key can then be read before its older records in the old partition have been consumed.
  3. Retries with idempotence off. With enable.idempotence=false, retries enabled and max.in.flight.requests.per.connection above 1, a retried batch can be written after a batch sent after it. If the first attempt had in fact succeeded, the record is duplicated as well.
  4. Several writers, or resends from application code. Two producer instances writing the same key have no order between them; the leader appends whatever arrives first. Code that resends a failed record from its callback appends it after everything sent in the meantime.
  5. The consumer processes in parallel. Handing the records of one partition to a thread pool, or to asynchronous calls that complete in any order, gives up the order in which Kafka delivered them.

How to fix it

What not to do

Configs involved

Reproduce it in the simulator

Sources

Related

All troubleshooting pages