What does max.in.flight.requests.per.connection control, and how does it interact with retries, ordering, and idempotence?
answer
- in-flight = sent-but-unacked per broker conn
- default 5, pipelines for throughput
- no-idempotence + retries + >1 = reorder risk
- old fix: set to 1
- idempotence: PID + seq num, ordered up to 5, >5 errors
basics
~20 sIt's the number of unacknowledged produce requests the producer allows per broker connection at once. Higher values pipeline more for throughput; with retries and no idempotence, values above 1 can reorder records on a failed-then-retried batch.
solid answer
~50 smax.in.flight.requests.per.connection (default 5) caps how many produce requests can be in flight (sent but not yet acked) per broker connection. Higher values pipeline requests so the producer isn't idle waiting for acks — key to high throughput, especially with acks=all where each request has more latency. The catch is ordering under retries: if request 1 fails and is retried while request 2 (already sent) succeeded, records can land out of order on that partition. Historically you set it to 1 to guarantee strict ordering with retries. The idempotent producer (enable.idempotence=true, default in modern clients) solves this: each batch carries a producer ID and monotonic sequence number, so the broker rejects out-of-order or duplicate batches and the client re-sequences retries. With idempotence, ordering is preserved for max.in.flight up to 5 — so you keep both pipelining throughput and ordering. Setting it above 5 with idempotence on throws a ConfigException.
go deeper
Know it's how many requests can be in flight at once and that higher helps throughput.
Explain the reorder-on-retry hazard and the old max.in.flight=1 fix.
Explain how idempotence (PID + sequence numbers) preserves order up to 5 in-flight and the >5 ConfigException.
Design producer configs balancing pipelining, ordering, and exactly-once guarantees across high-latency topologies.
## What it controls `max.in.flight.requests.per.connection` (default **5**) is the maximum number of **produce requests that have been sent to a broker but not yet acknowledged**, per TCP connection (one connection per broker). It governs **pipelining**: instead of send → wait-for-ack → send, the producer can have several requests outstanding simultaneously. ## Why it matters for throughput With `acks=all`, each request incurs leader + replication latency. If only one request could be in flight, the producer would sit idle during that latency, capping throughput at (batch bytes) / (round-trip time). Allowing 5 in flight overlaps the round-trips, so the link stays busy and throughput rises — often the single biggest lever for high-latency (e.g., cross-AZ or acks=all) links. ## The ordering hazard (without idempotence) Kafka guarantees order **within a partition** in the order the broker appends batches. Consider two batches B1 then B2 for the same partition, both in flight: 1. B1 fails (transient error), B2 succeeds and is appended. 2. The producer **retries B1**, which now appends **after** B2. 3. Result: records reordered on that partition. This can only happen when `max.in.flight > 1` **and** `retries > 0` **and** idempotence is **off**. The classic safe-but-slow fix was `max.in.flight.requests.per.connection=1`, which serializes requests and preserves order at a throughput cost. ## How idempotence fixes it `enable.idempotence=true` (default true in modern Kafka clients) assigns the producer a **Producer ID (PID)** and tags every batch per partition with a **monotonically increasing sequence number**. The broker tracks the last sequence it accepted per (PID, partition) and: - **Rejects duplicates** (a retry of an already-appended batch) → no double-write. - **Rejects out-of-order batches** (gap in sequence) with OutOfOrderSequenceException, forcing the client to re-send in order. The client buffers and re-sequences retries so the broker always sees an in-order sequence. This preserves ordering **even with up to 5 in-flight requests**, giving you pipelining throughput AND strict per-partition order. ## Constraints with idempotence - `max.in.flight.requests.per.connection` must be **<= 5** when idempotence is on; >5 throws ConfigException (the broker only deduplicates/orders against a bounded window of recent sequences). - Idempotence also requires `acks=all` and `retries > 0`. ## Edge cases / gotchas - Without idempotence, even `max.in.flight=2` with retries can reorder — it's not just large values. - Setting it to 1 hurts throughput most on high-latency links; prefer idempotence over =1 in modern clients. - Ordering is per-partition only; cross-partition order is never guaranteed regardless of this setting.
- Why does the idempotent producer cap max.in.flight at 5?The broker deduplicates and orders batches using a bounded window of the most recent sequence numbers per producer-partition. Limiting in-flight requests to 5 keeps retries within that window so the broker can reliably detect duplicates and gaps; allowing more would risk sequences outside the tracked window.
- If max.in.flight=1, do you still need idempotence for ordering?For ordering alone, max.in.flight=1 with retries already preserves order, since only one request is outstanding. But you'd still want idempotence to prevent duplicate writes from retries, and =1 sacrifices throughput, so idempotence with in-flight up to 5 is the better modern choice.
saying these in an interview costs you the question
- Saying any value >1 always reorders — only with retries AND no idempotence
- Claiming idempotence allows unlimited in-flight (capped at 5)
- Thinking the setting is per-producer rather than per-broker connection
- Believing it preserves cross-partition ordering (only per-partition)
- Recommending max.in.flight=1 in modern clients instead of idempotence