00:00

Kafka MirrorMaker

Kafka MirrorMaker is a tool provided by Apache Kafka that copies (replicates) data from one Kafka cluster to another. In simple words, it keeps topics in two different Kafka clusters in sync.

This guide explains why cross-cluster replication is needed, how MirrorMaker 2 works internally, how to configure and run it step by step, how topic names and consumer offsets are handled during failover, and how to monitor it, with formatted configuration, command-line and Java examples. It builds on Kafka Cluster and Kafka Connect.

1. What Is Kafka MirrorMaker?

Think of MirrorMaker as a bridge between two Kafka clusters. Messages produced to selected topics in the source cluster are automatically copied to the target cluster, usually within seconds.

MirrorMaker as a bridge
   Cluster A (source)                          Cluster B (target)
 +--------------------+                      +--------------------+
 |  orders            |    +------------+    |  A.orders          |
 |  payments          | -> | MirrorMaker| -> |  A.payments        |
 |  consumer offsets  |    |     2      |    |  translated offsets|
 +--------------------+    +------------+    +--------------------+

MirrorMaker is commonly used for:

  • Disaster recovery.
  • Multi-data-center and multi-region setups.
  • Migrating data between Kafka clusters.
  • Sharing data across teams or regions.

2. Why Do We Need Kafka MirrorMaker?

Kafka already replicates each partition across brokers inside one cluster, which protects against a broker or disk failure. It does not protect against losing a whole cluster or data center, and a single cluster stretched across distant regions would be slow.

In real-world systems, companies often run Kafka clusters in several locations, for example one in India and another in the US. If one cluster goes down, the data should still be available in the other. MirrorMaker continuously copies messages between clusters, so both have the same data.

Replication typeProtects againstHandled by
Inside one clusterBroker, disk or rack failureKafka partition replicas (replication factor)
Between clustersData center or region outage, migration needs, data sharingMirrorMaker 2 or similar tools

3. Key Features of Kafka MirrorMaker

FeatureExplanation
Cross-cluster replicationCopies topics from a source cluster to a target cluster, even across data centers or regions
Built on Kafka clientsInternally uses consumers to read from the source and producers to write to the target
Topic selectionReplicates one topic, a list, or patterns such as all topics starting with orders
Config and ACL syncCopies topic settings, partition counts and ACLs to the target
Offset translationRecords how source offsets map to target offsets so consumers can fail over
Fault tolerantRuns on Kafka Connect; if a worker fails, its tasks move to the others and resume from saved progress
ScalableReplication is split into tasks that run in parallel on several workers
Near real-timeMessages are copied continuously, typically within seconds

4. MirrorMaker 1 vs MirrorMaker 2

Kafka has had two generations of the tool:

AspectMirrorMaker 1 (legacy)MirrorMaker 2
Built onA simple consumer and producer pairKafka Connect connectors
Topic configuration syncNoYes, including partition counts and ACLs
New topicsPicked up through a topic patternDetected automatically at a regular interval
Consumer offset translationNoYes, through checkpoints
Loop prevention for two-way replicationNoYes, through remote topic names
StatusDeprecated, and removed in Kafka 4.0The supported tool

For all new projects, use MirrorMaker 2 (often written MM2). The rest of this tutorial covers MirrorMaker 2.

5. How MirrorMaker 2 Works

MirrorMaker 2 is a set of three Kafka Connect connectors that work together:

ConnectorJob
MirrorSourceConnectorCopies records from source topics to remote topics in the target, and syncs topic configs and ACLs
MirrorCheckpointConnectorTranslates consumer group offsets and writes them as checkpoints in the target
MirrorHeartbeatConnectorSends regular heartbeat records so you can check that replication is alive

MirrorMaker 2 also creates a few internal topics:

Internal topicPurpose
heartbeatsHeartbeat records showing that the link between clusters is working
A.checkpoints.internalTranslated consumer offsets for groups from cluster A, stored in the target
mm2-offset-syncs.B.internalMapping between source and target offsets, stored in the source by default
mm2-configs, mm2-offsets, mm2-status topicsKafka Connect’s own state for the MirrorMaker 2 connectors

6. Simple Example of Kafka MirrorMaker

Let’s understand this with a simple scenario:

  • Source cluster: Kafka cluster A (India).
  • Target cluster: Kafka cluster B (US).
  • Topic: order-events.

An application produces order messages to order-events in cluster A. MirrorMaker 2 is configured to:

  1. Consume messages from order-events in cluster A.
  2. Produce the same messages to A.order-events in cluster B. The A. prefix shows where the data came from.
  3. Translate the offsets of consumer groups reading in cluster A, so they can continue in cluster B.

Whenever a new order message is published in cluster A, it appears in cluster B shortly afterwards. If cluster A goes down, applications can read the order data from cluster B and continue close to where they stopped.

7. Running MirrorMaker 2 Step by Step

The simplest way to run MirrorMaker 2 is dedicated mode, using a script and one properties file that ship with Kafka.

Step 1: Create the configuration file

mm2.properties
# Names (aliases) for the two clusters
clusters = A, B
A.bootstrap.servers = kafka-a1:9092,kafka-a2:9092
B.bootstrap.servers = kafka-b1:9092,kafka-b2:9092

# Enable replication from A to B
A->B.enabled = true

# Topics and consumer groups to replicate (regular expressions)
A->B.topics = order-events, payments.*
A->B.groups = .*

# Translate consumer offsets into cluster B every 60 seconds
A->B.sync.group.offsets.enabled = true

# Replication factor for the copied topics in cluster B
replication.factor = 3

# Replication factor for MirrorMaker 2 internal topics
checkpoints.topic.replication.factor = 3
heartbeats.topic.replication.factor = 3
offset-syncs.topic.replication.factor = 3
offset.storage.replication.factor = 3
status.storage.replication.factor = 3
config.storage.replication.factor = 3

# Parallel tasks for copying data
tasks.max = 4

Step 2: Start MirrorMaker 2

Start in dedicated mode
bin/connect-mirror-maker.sh config/mm2.properties

Run the same command on two or more machines for high availability. The instances form a group and share the work automatically.

Step 3: Check the replicated topic

Verify in cluster B
# List topics in the target cluster
bin/kafka-topics.sh --bootstrap-server kafka-b1:9092 --list

# Read the mirrored messages
bin/kafka-console-consumer.sh --bootstrap-server kafka-b1:9092 \
  --topic A.order-events --from-beginning

Place MirrorMaker 2 close to the target cluster. Reading over a long network link and writing locally is more reliable than the other way round.

8. Remote Topic Names and Replication Policies

By default, MirrorMaker 2 uses the DefaultReplicationPolicy, which names each copied topic <source alias>.<topic>. These copies are called remote topics.

Source cluster topicTarget cluster topic
order-events in AA.order-events in B
payments-in in AA.payments-in in B

The prefix has two benefits: you can always see where data came from, and two-way replication cannot loop, because MirrorMaker 2 never copies A.order-events back to cluster A.

If you need identical names, for example during a one-way migration, use the IdentityReplicationPolicy:

Keep the same topic names
replication.policy.class = org.apache.kafka.connect.mirror.IdentityReplicationPolicy

With identical names, MirrorMaker 2 cannot tell local and copied topics apart, so use this policy only for one-way replication.

9. Consumer Offset Translation and Failover

Offsets in cluster B are different from offsets in cluster A: the same message may be at offset 5,000 in A and offset 1,200 in B. A consumer cannot simply reuse its old offset after failing over.

MirrorMaker 2 solves this with checkpoints. It regularly records how source offsets map to target offsets and writes each group’s translated position to the target cluster. With sync.group.offsets.enabled=true, it also commits these positions directly to the target’s consumer offsets, so a consumer that switches to cluster B with the same group.id starts close to where it stopped.

Failover in steps
1. Cluster A fails.
2. Stop consumers that were reading from cluster A.
3. Point consumers to cluster B (topic A.order-events, same group.id).
4. Consumers resume from the translated offsets.
5. A few recently processed messages may be read again.

Translation is not exact to the last message, and the newest messages may not have been copied when cluster A failed. Design consumers to be idempotent, so a few repeated messages cause no harm.

10. Working with Mirrored Topics in Java

A consumer in cluster B can read both the local topic and the remote copy with a regular-expression subscription:

MirroredOrdersConsumer.java
package com.example.kafka;

import java.time.Duration;
import java.util.Properties;
import java.util.regex.Pattern;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer;

public class MirroredOrdersConsumer {

    public static void main(String[] args) {
        Properties props = new Properties();
        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka-b1:9092");
        props.put(ConsumerConfig.GROUP_ID_CONFIG, "order-reporting");
        props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);

        try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props)) {
            // matches "order-events" and remote copies such as "A.order-events"
            consumer.subscribe(Pattern.compile("(.*\\.)?order-events"));

            while (true) {
                for (ConsumerRecord<String, String> record : consumer.poll(Duration.ofMillis(500))) {
                    System.out.printf("topic=%s offset=%d value=%s%n",
                            record.topic(), record.offset(), record.value());
                }
            }
        }
    }
}

To look up translated offsets yourself, for example in a failover script, use RemoteClusterUtils from the connect-mirror-client library:

pom.xml
<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>connect-mirror-client</artifactId>
    <version>4.0.0</version>
</dependency>
TranslateOffsets.java
package com.example.kafka;

import java.time.Duration;
import java.util.Map;

import org.apache.kafka.clients.consumer.OffsetAndMetadata;
import org.apache.kafka.common.TopicPartition;
import org.apache.kafka.connect.mirror.RemoteClusterUtils;

public class TranslateOffsets {

    public static void main(String[] args) throws Exception {
        // connection settings for the TARGET cluster (B)
        Map<String, Object> targetProps = Map.of("bootstrap.servers", "kafka-b1:9092");

        Map<TopicPartition, OffsetAndMetadata> offsets =
                RemoteClusterUtils.translateOffsets(
                        targetProps,
                        "A",                    // alias of the source cluster
                        "order-service",        // consumer group
                        Duration.ofSeconds(30));

        offsets.forEach((partition, offset) ->
                System.out.println(partition + " -> " + offset.offset()));
    }
}

The returned map can be passed to consumer.commitSync(offsets), or used with seek(), before the consumer starts reading from cluster B.

11. Replication Topologies: Active-Passive and Active-Active

TopologyHow it worksTypical use
Active-passiveA → B only; applications use A, and B is a standby copyDisaster recovery
Active-activeA → B and B → A; each region has local producers and reads both local and remote topicsMulti-region applications with low local latency
Hub and spokeSeveral edge clusters replicate into one central clusterCentral analytics, aggregating data from many sites
MigrationOld → new cluster, often with identical topic names, until clients switchMoving to new hardware, cloud or version
Active-active configuration
clusters = A, B
A.bootstrap.servers = kafka-a1:9092
B.bootstrap.servers = kafka-b1:9092

A->B.enabled = true
A->B.topics = order-events
B->A.enabled = true
B->A.topics = order-events

Here cluster B ends up with order-events (local writes) and A.order-events (copied from A), and cluster A has the mirror image. Consumers that need all orders subscribe to both topics, as in the Java pattern above.

12. Running MirrorMaker 2 on a Kafka Connect Cluster

If you already run a Kafka Connect cluster, you can deploy the MirrorMaker 2 connectors there through the Connect REST API instead of using the dedicated script:

Create the source connector
curl -X POST http://connect:8083/connectors \
  -H "Content-Type: application/json" \
  -d '{
    "name": "mm2-source-A-to-B",
    "config": {
      "connector.class": "org.apache.kafka.connect.mirror.MirrorSourceConnector",
      "source.cluster.alias": "A",
      "target.cluster.alias": "B",
      "source.cluster.bootstrap.servers": "kafka-a1:9092",
      "target.cluster.bootstrap.servers": "kafka-b1:9092",
      "topics": "order-events",
      "tasks.max": "4"
    }
  }'

Create MirrorCheckpointConnector and MirrorHeartbeatConnector the same way. This mode gives you Connect’s REST API and existing monitoring, but needs more configuration; dedicated mode is simpler to start with.

13. Monitoring MirrorMaker 2

What to watchWhy it matters
replication-latency-msTime between a record being written in the source and copied to the target
record-age-msAge of records when MirrorMaker reads them; a growing value means it is falling behind
Consumer lag of MirrorMaker on the sourceMessages waiting to be copied
Connector and task statusFailed tasks stop replication for their partitions
heartbeats topic in the targetNew heartbeat records prove that the link between clusters is working

These metrics are exposed through JMX, so they can be collected with tools such as Prometheus and shown in dashboards. Alert when replication latency keeps rising or when heartbeats stop arriving.

14. Real-World Use Cases

Use caseHow MirrorMaker 2 helps
Disaster recoveryKeeps a standby cluster with recent data and translated offsets, ready for failover
Geo-replicationShares data across regions so local applications read from a nearby cluster
Data migrationMoves topics from an old cluster to a new one while both keep running
AnalyticsCopies production data to a separate analytics cluster, so heavy reports do not affect production
Edge to cloudCollects data from many smaller clusters, such as factories or stores, into one central cluster

15. Limitations to Know

  • Asynchronous copy: if the source fails, the newest messages may not have reached the target yet.
  • At-least-once by default: after a restart, some records may be copied twice. Newer Kafka versions can be configured for exactly-once copying, but it needs extra setup.
  • Different offsets: offsets in the target do not match the source; consumers rely on offset translation.
  • Network cost: all replicated data crosses the network between sites, which can be slow or expensive.
  • Not a backup of everything: it does not copy broker settings, users or data from topics you did not select.

16. Best Practices

DoAvoid
Use MirrorMaker 2 for all new setupsStarting new projects with the legacy MirrorMaker 1
Run MirrorMaker 2 near the target clusterWriting to a distant cluster over a slow link
Run at least two instances for high availabilityA single MirrorMaker process for important data
Use replication factor 3 for remote and internal topicsLeaving low defaults on production copies
Keep the default replication policy for two-way replicationIdentity names with active-active, which can create loops
Enable offset sync and practise failover regularlyDiscovering failover problems during a real outage
Make consumers idempotentAssuming no message is ever repeated after failover
Monitor replication latency and heartbeatsNoticing broken replication only when it is needed
Secure both connections with TLS and authenticationSending data between data centers unencrypted

17. Summary

Kafka MirrorMaker is a simple and powerful tool for replicating Kafka topics from one cluster to another. MirrorMaker 2, built on Kafka Connect, is the version to use today: it copies records, topic settings and ACLs, renames copied topics to show their source and prevent loops, translates consumer offsets for failover, and reports its health through heartbeats and metrics. Configure it with a single properties file, run several instances near the target cluster, and plan for asynchronous replication by making consumers idempotent.

By copying messages in near real time, MirrorMaker helps build reliable, scalable and fault-tolerant systems, and it is an essential component for anyone running Kafka across several data centers or regions.