An order router reads an accepted order and publishes it to two topics: one for reporting and one for an audit pipeline. It then saves its input progress. If it crashes after only the reporting write succeeds, the two destinations disagree. If both writes succeed but the offset commit fails, recovery can publish both again.
Kafka transactions let the application give these Kafka operations one shared outcome. The output records and input offsets can commit together, or Kafka can abort the attempt.
In this chapter, we’ll follow that lifecycle, explain transactional visibility, and build a Java router that coordinates its outputs with its progress. The examples use Apache Kafka 4.3.1 and its Java client in a KRaft-based cluster, with ordinary consumer groups and all participating topics in the same cluster.