Skip to content
Kafka Is Fun

Lesson 3 of 3

Exactly-Once Semantics (EOS)

1 min read

Overview

Within Kafka, exactly-once means that processing a record, and writing its results to Kafka topics, happens once. There are two routes. Kafka Streams with processing.guarantee=exactly_once_v2 uses transactions to cover input offsets, state stores and output writes atomically; it is opt-in, because the default is at_least_once. With plain clients, you use a transactional producer (transactional.id) that sends the consumer's offsets in the same transaction, plus a consumer with isolation.level=read_committed and enable.auto.commit=false. The idempotent producer alone only prevents duplicate log entries from producer retries within a single session. For a destination outside Kafka, exactly-once needs that system's cooperation, for example storing the offset with the output. The Streams documentation notes that exactly-once needs at least three brokers and that a replication factor below 3 effectively voids it. The improved implementation arrived in Kafka 2.6.0, and KIP-732 (Kafka 3.0) deprecated exactly_once and exactly_once_beta in favour of exactly_once_v2.

Key configuration

Settingsproperties
# Kafka Streams
processing.guarantee=exactly_once_v2   # opt-in; the default is at_least_once

# Plain clients
transactional.id=unique-producer-id
isolation.level=read_committed          # consumer; the default is read_uncommitted
enable.auto.commit=false                # consumer

Production tip

Check yourself

Within Kafka, which setup gives exactly-once processing for a read-process-write application?

Sources

Checked against Kafka 4.2 documentation on Oct 2026. Draft: not yet reviewed by a Kafka specialist. Releases move on, so confirm against the current documentation before you act on a number.

Try it in the simulator

Guided scenarios for this module — the simulator opens with the exercise already running.

Prefer a picture? Open the live cluster in 3D and watch records move between producer, brokers and consumers.

Browse all troubleshooting entries