---
title: "Kafka transaction commit vs abort with read_committed"
description: "Two transactions on one Kafka partition: a commit moves the last stable offset so read_committed reads the batch; an abort marks the range and it is skipped."
url: https://monedula.dev/kafka-simulator/scenarios/txn-commit-vs-abort/
---

# Kafka transaction commit vs abort with read_committed

Scenario 04.2.1 · Transactional write: commit vs abort. Transactions · Advanced · about 3 min · Apache Kafka 4.3.

One partition, two transactions: commit makes the batch visible to read_committed; abort marks the range aborted and a read_committed consumer skips it entirely.

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

## What you start with

The atom of a Kafka transaction shown twice on one partition while a read_committed consumer watches: one transaction that commits and one that aborts. Records are physically appended (the high-watermark advances) in both cases - only the Last Stable Offset (LSO) and read_committed delivery tell them apart.

## Step by step

1. **Cluster ready · read_committed** (t+0.000s): One partition (RF 3, min.ISR 2), a transactional producer, and a read_committed consumer. read_committed only delivers records up to the Last Stable Offset (LSO) - never records inside an open or aborted transaction. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.2.1&t=0)
2. **begin txn 1** (t+0.100s): begin_transaction moves the producer to `ongoing`. This is client-side only: the coordinator learns of the transaction, and starts its timeout, when the first partition is added. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.2.1&t=1)
3. **Produced · uncommitted** (t+1.100s): Two records were appended and replicated - the high-watermark advanced to 2, so they are durable. But the LSO stays pinned at 0: the records are physically in the log yet uncommitted, so a read_committed consumer cannot see them. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.2.1&t=2)
4. **commit · LSO advances** (t+1.900s): commit_transaction writes a commit marker and the LSO advances to the high watermark (2), so the read_committed consumer advances to 2. In Kafka the marker is a control record with its own offset (2 here), so the log end, LSO and position would be 3; the simulator gives markers no offset. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.2.1&t=3)
5. **begin txn 2** (t+2.400s): A second transaction opens on the same partition. Same starting point: records will append but stay invisible until this txn resolves. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.2.1&t=4)
6. **Produced · uncommitted** (t+3.100s): Two more records append (HW = 4), again held below the LSO (still 2). So far this is identical to txn 1 - the raw log cannot yet tell a doomed batch from a good one. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.2.1&t=5)
7. **abort · range skipped** (t+4.000s): abort_transaction records the range [2,4) in abortedRanges and releases the LSO PAST it to 4. The read_committed consumer advances its position over the range but delivers NONE of those records - the aborted batch is discarded. The HW advanced for both batches; only commit-vs-abort decided what is visible. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.2.1&t=6)

## The takeaway

Committing advances the LSO so read_committed can read the batch; aborting writes an abort marker, records the aborted offset range and releases the LSO past it, so a read_committed consumer steps over the aborted records and delivers none of them.

## Configs in this scenario

- [`min.insync.replicas`](https://kafka.apache.org/43/configuration/topic-configs/#topicconfigs_min.insync.replicas): The fewest in-sync replicas, leader included, that must have a write for an acks=all produce to succeed (default 1); with fewer in the ISR the leader rejects the write with NOT_ENOUGH_REPLICAS. [How min.insync.replicas works](https://monedula.dev/kafka-simulator/configs/min-insync-replicas/)

## Further reading

- [Apache Kafka documentation](https://kafka.apache.org/43/configuration/consumer-configs/#consumerconfigs_isolation.level)
