Scenario 09.2.4 · Offset translation across clusters
MirrorMaker 2 offset translation for Kafka consumer failover
MM2 checkpoints the committed offset, translated to the DR cluster. Fail over and the consumer resumes at the last checkpoint - reprocessing the un-checkpointed tail.
Run this scenario in the playgroundTwo regions ready - consumer reads on primary, MM2 mirrors to dr. t+0.000s
primary serves orders; the mm-1 link mirrors committed records into dr's MM2 topic primary.orders. Checkpoints run every 1000 ms here (real MM2: emit.checkpoints.interval.seconds, 60 s by default): MM2 will periodically checkpoint g1's committed offset, translated into dr's offset space.
Open at this step: step 1, Two regions ready - consumer reads on primary, MM2 mirrors to drFirst checkpoint: committed offset 3 translated to dr. t+1.100s
g1 has consumed and committed offsets 0,1,2 (committed = 3). The t=1000 checkpoint records that translated offset on the link (open the mm-1 link inspector → offset checkpoints). The mirror has kept up so RPO is 0.
Open at this step: step 2, First checkpoint: committed offset 3 translated to drConsumer commits past the checkpoint - reprocess window opens. t+1.600s
p1 produced O4,O5; g1 commits up to 5. But the next checkpoint isn't until t=2000, so offsets 3,4 are committed-but-not-checkpointed. Fail over now and the consumer would re-read those 2 records - the reprocess window.
Open at this step: step 3, Consumer commits past the checkpoint - reprocess window opensFailover: consumer resumes at the checkpoint (offset 3), not 5. t+1.810s
g1 is promoted onto dr's primary.orders. Offset translation resumes it at the last checkpointed offset (3), NOT its live committed (5) - so records 3,4 will be reprocessed. RPO is still 0 (all data mirrored); the only cost is reprocessing the un-checkpointed tail.
Open at this step: step 4, Failover: consumer resumes at the checkpoint (offset 3), not 5Consumer catches up on dr; a new produce lands on the promoted region. t+2.400s
g1 re-reads offsets 3,4 then the new O6 (produced to dr's primary.orders after promotion), draining back to the dr high-watermark. Writing the mirror topic is a simulator shortcut: MM2 expects producers to write only local topics, so a real p1 would write a dr-local orders. A shorter checkpoint interval would have shrunk the reprocess window; a longer one would have grown it.
Open at this step: step 5, Consumer catches up on dr; a new produce lands on the promoted regionWhat you start with
When MirrorMaker 2 re-produces records into the DR cluster, the DR offsets can drift from the source offsets and the group's commits stay on the source, so a failed-over consumer cannot reuse its primary offsets directly. MM2’s checkpoint connector periodically records the group’s committed offset translated into the DR offset space. The consumer keeps committing after the last checkpoint; on failover it resumes at that checkpoint, reprocessing the un-checkpointed tail.
Step by step
- Two regions ready - consumer reads on primary, MM2 mirrors to dr t+0.000s primary serves orders; the mm-1 link mirrors committed records into dr's MM2 topic primary.orders. Checkpoints run every 1000 ms here (real MM2: emit.checkpoints.interval.seconds, 60 s by default): MM2 will periodically checkpoint g1's committed offset, translated into dr's offset space. Open at this step: step 1, Two regions ready - consumer reads on primary, MM2 mirrors to dr
- First checkpoint: committed offset 3 translated to dr t+1.100s g1 has consumed and committed offsets 0,1,2 (committed = 3). The t=1000 checkpoint records that translated offset on the link (open the mm-1 link inspector → offset checkpoints). The mirror has kept up so RPO is 0. Open at this step: step 2, First checkpoint: committed offset 3 translated to dr
- Consumer commits past the checkpoint - reprocess window opens t+1.600s p1 produced O4,O5; g1 commits up to 5. But the next checkpoint isn't until t=2000, so offsets 3,4 are committed-but-not-checkpointed. Fail over now and the consumer would re-read those 2 records - the reprocess window. Open at this step: step 3, Consumer commits past the checkpoint - reprocess window opens
- Failover: consumer resumes at the checkpoint (offset 3), not 5 t+1.810s g1 is promoted onto dr's primary.orders. Offset translation resumes it at the last checkpointed offset (3), NOT its live committed (5) - so records 3,4 will be reprocessed. RPO is still 0 (all data mirrored); the only cost is reprocessing the un-checkpointed tail. Open at this step: step 4, Failover: consumer resumes at the checkpoint (offset 3), not 5
- Consumer catches up on dr; a new produce lands on the promoted region t+2.400s g1 re-reads offsets 3,4 then the new O6 (produced to dr's primary.orders after promotion), draining back to the dr high-watermark. Writing the mirror topic is a simulator shortcut: MM2 expects producers to write only local topics, so a real p1 would write a dr-local orders. A shorter checkpoint interval would have shrunk the reprocess window; a longer one would have grown it. Open at this step: step 5, Consumer catches up on dr; a new produce lands on the promoted region
The takeaway
Offset translation lets a consumer resume on the DR cluster after failover, but only as of the last checkpoint - so the checkpoint cadence sets the reprocess window (at-least-once across clusters), even when RPO is zero.
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=09.2.4" title="Kafka Simulator: Offset translation across clusters" width="100%" height="520" style="border:1px solid #d0d0d0;border-radius:8px" loading="lazy"></iframe>
<p><a href="https://monedula.dev/kafka-simulator/scenarios/offset-translation-checkpoint/">MirrorMaker 2 offset translation for Kafka consumer failover</a></p> Further reading
More in Disaster recovery
- Kafka stretched cluster across two data centers
- 2.5-DC Kafka stretched cluster with a witness site
- 3-DC Kafka cluster: the KRaft quorum survives losing a site
- Kafka in two DCs without a witness: KRaft quorum is lost
- Kafka data center failure: leader failover to the other DC
- Kafka network split inside one DC: ISR drops to the floor
- Kafka MirrorMaker 2 active-passive DR and replication lag
- Kafka DR failover with MirrorMaker 2: measuring RPO
- Active-active Kafka with MirrorMaker 2 and region topics
- Kafka failback after a MirrorMaker 2 DR failover
- Active-active Kafka DR drill: move clients to the survivor
- Confluent MRC observers: Kafka replicas outside the ISR
- Kafka observer lag in Confluent Multi-Region Clusters
- Kafka observer promotion in Confluent Multi-Region Clusters
- Confluent MRC observer promotion: losing the Kafka leader DC
- Kafka replica placement: durability vs latency across DCs
- Confluent Cluster Linking: offset-preserving Kafka mirroring
- Kafka mirror topics (Confluent): read-only until promoted
- Cluster Linking vs MirrorMaker 2 for Kafka replication
- Kafka consumer offset sync: Cluster Linking vs MirrorMaker 2
- Kafka failover and failback with Confluent Cluster Linking