Scenario 11.0.4 · Acknowledge: accept, release, reject
Kafka share consumer acknowledge: accept, release, reject
The three share-group acknowledgement outcomes and the record-state transitions each drives - accept→acked, release→available (redelivered), reject→archived (KIP-932).
Run this scenario in the playgroundCluster ready · idle. t+0.000s
One partition, one share group (member w1) in EXPLICIT ack mode with a long 5000ms lock so all three records stay held while we apply one of each ack type. Press ▶.
Open at this step: step 1, Cluster ready · idleThree records acquired in-flight. t+0.750s
First poll (700ms) acquires offsets 0/1/2 (max.poll.records=3), all locked to w1, deliveryCount=1. In explicit mode they stay 'acquired' until acknowledged.
Open at this step: step 2, Three records acquired in-flightACCEPT offset 0 → acked. t+0.900s
w1 accepts offset 0: state → 'acked'. Accept means processed successfully and terminal - it will never be redelivered, and the share-partition start offset can advance past it.
Open at this step: step 3, ACCEPT offset 0 → ackedRELEASE offset 1 → available. t+1.100s
w1 releases offset 1: state → 'available'. Release returns the record to the queue un-processed so it can be redelivered (to any member) on a later poll.
Open at this step: step 4, RELEASE offset 1 → availableREJECT offset 2 → archived. t+1.300s
w1 rejects offset 2: state → 'archived'. Reject is terminal like accept but marks the record as NOT to be reprocessed (a poison-pill drop) - it never comes back. Offset 1 is still 'available', waiting for the next poll.
Open at this step: step 5, REJECT offset 2 → archivedReleased record redelivered. t+1.500s
The next poll (1400ms) re-acquires offset 1 (deliveryCount=2) - only the RELEASED record returns. Accepted (0) and rejected (2) are both terminal and stay put.
Open at this step: step 6, Released record redeliveredWhat you start with
Explicit acknowledgement gives a share consumer three outcomes per record. A single member acquires all three records in one poll under a long lock, then applies one of each: accept marks a record ACKED (done), release returns it to AVAILABLE for redelivery, and reject ARCHIVES it (skipped, never redelivered).
Step by step
- Cluster ready · idle t+0.000s One partition, one share group (member w1) in EXPLICIT ack mode with a long 5000ms lock so all three records stay held while we apply one of each ack type. Press ▶. Open at this step: step 1, Cluster ready · idle
- Three records acquired in-flight t+0.750s First poll (700ms) acquires offsets 0/1/2 (max.poll.records=3), all locked to w1, deliveryCount=1. In explicit mode they stay 'acquired' until acknowledged. Open at this step: step 2, Three records acquired in-flight
- ACCEPT offset 0 → acked t+0.900s w1 accepts offset 0: state → 'acked'. Accept means processed successfully and terminal - it will never be redelivered, and the share-partition start offset can advance past it. Open at this step: step 3, ACCEPT offset 0 → acked
- RELEASE offset 1 → available t+1.100s w1 releases offset 1: state → 'available'. Release returns the record to the queue un-processed so it can be redelivered (to any member) on a later poll. Open at this step: step 4, RELEASE offset 1 → available
- REJECT offset 2 → archived t+1.300s w1 rejects offset 2: state → 'archived'. Reject is terminal like accept but marks the record as NOT to be reprocessed (a poison-pill drop) - it never comes back. Offset 1 is still 'available', waiting for the next poll. Open at this step: step 5, REJECT offset 2 → archived
- Released record redelivered t+1.500s The next poll (1400ms) re-acquires offset 1 (deliveryCount=2) - only the RELEASED record returns. Accepted (0) and rejected (2) are both terminal and stay put. Open at this step: step 6, Released record redelivered
The takeaway
Choosing accept, release, or reject per record is how a share consumer expresses success, retry, and give-up - the per-message control a single classic offset commit cannot give you.
Configs in this scenario
-
max.The most records one poll() returns (default 500); a smaller value shortens the processing between two polls, which keeps a group member inside max.poll.interval.ms.poll. records
Embed this scenario
Paste this into a blog post, a course page or your team's docs. The scenario plays inside your page, and the link under it points readers to this walkthrough.
<iframe src="https://monedula.dev/kafka-simulator/embed/?scenario=11.0.4" title="Kafka Simulator: Acknowledge: accept, release, reject" width="100%" height="520" style="border:1px solid #d0d0d0;border-radius:8px" loading="lazy"></iframe>
<p><a href="https://monedula.dev/kafka-simulator/scenarios/acknowledge-accept-release-reject/">Kafka share consumer acknowledge: accept, release, reject</a></p> Further reading
KIP-932 on the Apache Kafka wiki
More in Share groups
- Kafka share groups: queue semantics with KIP-932
- More Kafka consumers than partitions with share groups
- Kafka share group acquisition lock timeout and redelivery
- Kafka share group poison pill: delivery limit and archiving
- Kafka share.acknowledgement.mode: implicit vs explicit
- Kafka share.acquire.mode: batch_optimized vs record_limit
- Renew a Kafka share group acquisition lock (KIP-1222)
- Kafka share group lag: SPSO, SPEO and the acked prefix