---
title: "Kafka max.in.flight.requests.per.connection and ordering"
description: "With idempotence off and max.in.flight=2, a retried record lands after a later one: log [A, B, A]. At max.in.flight=1 Kafka keeps produce order."
url: https://monedula.dev/kafka-simulator/scenarios/max-in-flight-ordering/
---

# Kafka max.in.flight.requests.per.connection and ordering

Scenario 01.3.4 · Out-of-order detection and max.in.flight. Producers & EOS · Intermediate · about 3 min · Apache Kafka 4.3.

With idempotence OFF, max.in.flight>1 lets a retried earlier batch land after a later one (reorder); max.in.flight=1 (or idempotence ON) preserves produce order.

Run it: https://monedula.dev/kafka-simulator/playground/?scenario=01.3.4

## What you start with

max.in.flight.requests.per.connection caps how many un-acked produce requests may be on the connection at once - and with idempotence OFF it is the ordering knob. Half 1 uses max.in.flight=2: a retried earlier record (A) lands AFTER a later one (B), giving log [A, B, A]. Half 2 drops it to 1, blocking later sends until the retry commits, so order is preserved as [C, C, D].

## Step by step

1. **p1 - idempotence OFF, max.in.flight = 2** (t+0.000s): One non-idempotent producer on orders/0. max.in.flight.requests.per.connection = 2 lets more than one produce request be in flight at once - the setting that, with idempotence off, lets a retry reorder the log. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.4&t=0)
2. **A committed at offset 0** (t+1.100s): A is produced and commits durably at offset 0 (acks=all). Its ack is now on the way back to the producer. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.4&t=1)
3. **A's ack is lost - p1 retries A (deferred)** (t+3.000s): drop_ack loses A's acknowledgement, so p1 must re-send A. Because max.in.flight > 1, the connection still accepts other requests while this retry waits out retry.backoff.ms - leaving a window for a later batch to slip ahead. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.4&t=2)
4. **B commits at offset 1 - ahead of the retried A** (t+3.300s): B is produced during the retry window and commits at offset 1, AHEAD of A's still-pending retry. The log is now [A, B] - but A's retry has not landed yet. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.4&t=3)
5. **A'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](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.4&t=4)
6. **max.in.flight → 1** (t+5.000s): A config change drops max.in.flight.requests.per.connection to 1 (live in the simulator; a real producer is recreated with it). Now the connection holds a single in-flight request at a time, so the producer blocks later sends until each retry commits. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.4&t=5)
7. **C committed at offset 3** (t+7.000s): C is produced and commits at offset 3. Its ack is in flight, just like A's was. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.4&t=6)
8. **C's ack is lost - the retry re-appends at offset 4** (t+8.000s): drop_ack loses C's ack. With max.in.flight = 1 the producer cannot have a later request outstanding, so nothing can overtake the retry (the simulator re-appends it in the same tick at offset 4; real Kafka still waits retry.backoff.ms). [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.4&t=7)
9. **D commits at offset 5 - order preserved** (t+8.300s): D is produced only after C's retry settled, landing at offset 5. The log tail is [C, C, D]: C's retry stayed ahead of D. max.in.flight = 1 preserved produce order - though C is still duplicated (only idempotence removes that). [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.4&t=8)
10. **Final log - reorder then order preserved** (t+9.200s): Full log [A, B, A, C, C, D]. Offsets 0-2: max.in.flight = 2 let A's retry land after B (reorder). Offsets 3-5: max.in.flight = 1 kept C's retry ahead of D (order preserved). max.in.flight controls ORDER; idempotence (01.3.1 / 01.3.3) is what removes the duplicates. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=01.3.4&t=9)

## The takeaway

With a non-idempotent producer, max.in.flight>1 can reorder the log when a retry overtakes a later batch; set max.in.flight=1, or enable idempotence, to keep produce order. Note max.in.flight controls order, not de-duplication - duplicates persist until idempotence is on.

## Configs in this scenario

- [`max.in.flight.requests.per.connection`](https://kafka.apache.org/43/configuration/producer-configs/#producerconfigs_max.in.flight.requests.per.connection): How many unacknowledged requests the producer sends on one connection (default 5); above 1 without idempotence a retried batch can land after a later one, and idempotence needs 5 or fewer. [How max.in.flight.requests.per.connection works](https://monedula.dev/kafka-simulator/configs/max-in-flight-requests-per-connection/)
- [`acks`](https://kafka.apache.org/43/configuration/producer-configs/#producerconfigs_acks): How many replicas must have a write before the producer counts it as sent: 0 (none), 1 (the leader only) or all (every in-sync replica, the default, and required for idempotence). [How acks works](https://monedula.dev/kafka-simulator/configs/acks/)
- [`retry.backoff.ms`](https://kafka.apache.org/43/configuration/producer-configs/#producerconfigs_retry.backoff.ms): How long the producer waits before retrying a failed send, so it does not hammer a broker that is still recovering.

## Further reading

- [Apache Kafka documentation](https://kafka.apache.org/43/configuration/producer-configs/#producerconfigs_max.in.flight.requests.per.connection)

## Troubleshooting

- [Kafka messages out of order: causes and fixes](https://monedula.dev/kafka-simulator/troubleshooting/messages-out-of-order/)
