Monedula

Scenario 04.2.2 · Transactions & read_committed

Kafka isolation.level: read_committed vs read_uncommitted

Transactions · Advanced · about 3 min · Apache Kafka 4.3

A transactional producer commits atomically across partitions; read_committed lags the LSO and skips an aborted batch.

Run this scenario in the playground

abort · range skipped. t+3.600s

abort_transaction records the aborted range and jumps the LSO past it. read_committed skips the aborted record entirely - it is never delivered to rc, while ru already saw it.

Open at this step: step 6, abort · range skipped

What you start with

A transactional producer commits atomically across two partitions, then runs a second transaction it aborts. Two consumer groups read the same topic - one read_committed, one read_uncommitted - so you can compare exactly what each isolation level sees.

Step by step

  1. Cluster ready · two groups t+0.000s orders has 2 partitions, RF=3, min.ISR=2. Group rc is read_committed, ru is read_uncommitted. A transactional producer tx1 is idle. Press ▶. Open at this step: step 1, Cluster ready · two groups
  2. begin transaction t+0.100s tx1 opens a transaction (transactional.id tx-app-1). Nothing is written yet. Open at this step: step 2, begin transaction
  3. Produced · uncommitted t+1.000s tx1 wrote one record to each partition. Both records are replicated (HW advanced), so read_uncommitted (ru) sees them - but the LSO is frozen, so read_committed (rc) is stuck and sees nothing. Neither partition's record is visible to rc until the transaction commits. Open at this step: step 3, Produced · uncommitted
  4. commit · LSO advances t+1.900s commit_transaction advances the LSO to the high watermark on both partitions and rc sees the whole transaction. The simulator does both in one step; in Kafka the markers land on each partition separately, so a reader can briefly see one partition's records before the other's. Open at this step: step 4, commit · LSO advances
  5. Second txn · uncommitted t+2.900s tx1 began a second transaction and wrote one more record to p0. ru briefly sees it; rc remains at the committed LSO. Open at this step: step 5, Second txn · uncommitted
  6. abort · range skipped t+3.600s abort_transaction records the aborted range and jumps the LSO past it. read_committed skips the aborted record entirely - it is never delivered to rc, while ru already saw it. Open at this step: step 6, abort · range skipped

The takeaway

read_uncommitted sees records the moment they are written, while read_committed lags at the LSO and never delivers the aborted batch - isolation.level is what makes transactional output safe to consume.

Configs in this scenario

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=04.2.2" title="Kafka Simulator: Transactions &amp; read_committed" width="100%" height="520" style="border:1px solid #d0d0d0;border-radius:8px" loading="lazy"></iframe>
<p><a href="https://monedula.dev/kafka-simulator/scenarios/transactions-read-committed/">Kafka isolation.level: read_committed vs read_uncommitted</a></p>

Further reading

Apache Kafka documentation

More in Transactions

All scenarios