---
title: "Kafka zombie producer fencing with transactional.id"
description: "A transactional producer commits output and input offsets together. A stale-epoch zombie with the same transactional.id tries to write, and Kafka fences it."
url: https://monedula.dev/kafka-simulator/scenarios/eos-fencing/
---

# Kafka zombie producer fencing with transactional.id

Scenario 04.3.2 · EOS - offsets in a txn + fencing. Transactions · Advanced · about 3 min · Apache Kafka 4.3.

Consume-process-produce commits input offsets inside the output transaction; a stale-epoch zombie producer is fenced.

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

## What you start with

Exactly-once semantics with producer fencing. A transactional producer runs a consume-process-produce transaction - committing the output record and the input offsets together - then a stale-epoch 'zombie' instance sharing the same transactional.id wakes up and tries to begin its own transaction.

## Step by step

1. **Cluster ready · EOS app** (t+0.000s): orders has 1 partition, RF=3. Group eos is read_committed with enable.auto.commit=off. tx is the live producer instance (epoch 1); tx-zombie is an old instance of the same transactional.id (epoch 0). Press ▶. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.3.2&t=0)
2. **begin txn 1** (t+0.100s): tx opens transaction 1 (transactional.id tx-app). [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.3.2&t=1)
3. **Produced · uncommitted** (t+1.100s): tx wrote two records; the HW advanced but the LSO is frozen, so read_committed eos sees nothing yet. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.3.2&t=2)
4. **txn 1 committed · read, no auto-commit** (t+1.900s): commit advances the LSO and eos reads both records (position 2). But committed stays at 0: enable.auto.commit is off, so offsets move only through the transaction. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.3.2&t=3)
5. **txn 2 · offsets staged** (t+2.900s): In a second txn tx produced an output record and called sendOffsetsToTransaction(eos): eos offsets {0:2} are staged inside the transaction, not yet committed. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.3.2&t=4)
6. **commit · offsets + output atomic** (t+3.400s): commit_transaction commits the output record AND eos input offsets atomically - eos.committed jumps to {0:2}. On an abort neither would commit: exactly-once. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.3.2&t=5)
7. **zombie fenced** (t+3.900s): tx-zombie (epoch 0) tries to open a new transaction, but tx holds a newer epoch, so the zombie is FENCED and can never write duplicates. In Kafka the fence lands on its first send or commit, since beginTransaction() is client-side, and transaction.version=2 bumps the epoch at every commit. [Open at this step](https://monedula.dev/kafka-simulator/playground/?scenario=04.3.2&t=6)

## The takeaway

The coordinator fences the zombie because only the latest producer epoch may write - a partitioned-then-recovered task can never corrupt the committed stream.

## Configs in this scenario

- [`transactional.id`](https://kafka.apache.org/43/configuration/producer-configs/#producerconfigs_transactional.id): A stable name that turns on transactions for a producer (and implies idempotence); a new producer that calls initTransactions() with the same id fences the older one.
- [`enable.auto.commit`](https://kafka.apache.org/43/configuration/consumer-configs/#consumerconfigs_enable.auto.commit): Whether the consumer commits its offsets in the background every auto.commit.interval.ms (default true); with it on, records processed between the last commit and a crash are read again.

## Further reading

- [Apache Kafka documentation](https://kafka.apache.org/43/configuration/producer-configs/#producerconfigs_transactional.id)

## Troubleshooting

- [ProducerFencedException in Kafka: causes and fixes](https://monedula.dev/kafka-simulator/troubleshooting/producer-fenced/)
