← All articles

Percona ClusterSync 1.0.0 Adds Automatic Failover for MongoDB

Percona ClusterSync 1.0.0 Adds Automatic Failover for MongoDB

Percona ClusterSync for MongoDB, the tool that moves data between MongoDB clusters, has reached version 1.0.0 with a built-in active-standby high availability mode. In a blog post published on September 30, 2026, author Adnan Supic, with an editor's note crediting Inel Pandzic, explains that until now, ClusterSync was a single point of failure: if the host, container, or pod running the tool crashed, replication stopped and an operator had to notice the outage and manually recover the process. The new release lets operators run multiple instances against the same source and target clusters so that a standby instance takes over automatically when the active one fails.

How the new mode works is straightforward. You can now run multiple Percona ClusterSync instances pointed at the same source and target MongoDB clusters. The instances coordinate through a MongoDB-backed lease stored on the target cluster, in a database called percona_clustersync_mongodb. Exactly one instance holds the lease and is ACTIVE, meaning it runs replication. The rest stay STANDBY and watch for the lease to expire. There is no external coordinator; the target MongoDB cluster you already have acts as the source of truth. High availability is always on and requires zero configuration changes. A single instance simply wins the lease immediately and behaves exactly as before. If you want failover, start a second or third instance with the same source and target, and the deployment is done.

Three mechanisms make failover safe: lease-based election, term fencing, and checkpoint-based recovery. Lease election avoids split-brain because all coordination state lives in the percona_clustersync_mongodb database on the target. Election is a single atomic conditional write: an instance claims the lease only if the current one has expired, and expiry is evaluated against the server clock. Two racing standbys cannot both win, and clock skew between ClusterSync hosts is irrelevant because MongoDB's clock is the only one that matters. The lease itself is one small document with fields for the lease identifier, term, instance ID, election date, and expiry time.

Term-based fencing prevents a classic distributed-systems failure known as a zombie write. The term field is a monotonic fencing token that increments on every election, every change from ACTIVE to STANDBY, and it is stamped into every checkpoint write the ACTIVE makes in percona_clustersync_mongodb.checkpoints. If an ACTIVE stalls due to a garbage collection pause, network partition, or a pod being killed and restarted before the lease expired, its lease expires, a standby is promoted, and the old instance may wake up and try to write as if nothing happened. With term fencing, that zombie active carries a stale term, the target rejects its checkpoint writes, the deposed instance notices, and it self-demotes to STANDBY. The new ACTIVE state is never corrupted.

On promotion, the new ACTIVE resumes replication from the persisted checkpoint, the same crash-recovery mechanism ClusterSync has always used, now triggered automatically. Timings are fixed in this release: the lease TTL is 10 seconds, the ACTIVE renews every 3 seconds, and each instance heartbeats every 3 seconds. In practice, a hard-killed ACTIVE is replaced within roughly the lease TTL. One boundary to know: high availability covers the change-stream replication phase, but the initial clone is not resumable. If the ACTIVE dies mid-clone, a standby is still promoted, detects the interrupted clone during recovery, and fails cleanly with an explicit reason in the logs and /status: initial clone interrupted by failover and is not resumable; start a new run to re-clone from scratch. Recovery is a plain /start on the new ACTIVE, which restarts the sync from scratch. Automatic failover kicks in once the clone completes and continuous replication begins.

Operating an HA deployment is designed to be explicit rather than guesswork. Each instance maintains a liveness document in percona_clustersync_mongodb.members on the target, and API responses include a cluster envelope so an operator hitting any node can see who is ACTIVE, the instance you reached, the role, and the full member list with every live instance host, port, and role. If you send an operational command such as /start, /pause, or /finalize to a STANDBY, it responds with HTTP 409 and error not_active, with the same envelope in the body, so your client can immediately locate the ACTIVE and retry there. The envelope appears only when more than one live member is observed; a lone instance returns responses byte-identical to the pre-HA API, so existing tooling keeps working unchanged. The /metrics and pprof endpoints are served on every role. For cleanup, two new direct commands clear HA state on the target while no server is running: pcsm reset members and pcsm reset lease.

Observability is built in. Each instance exports HA metrics on /metrics, on every role: percona_clustersync_mongodb_ha_active is a gauge where 1 means ACTIVE and 0 means STANDBY; percona_clustersync_mongodb_ha_term is a gauge for the current lease term; percona_clustersync_mongodb_ha_role_transitions_total is a counter for role changes on this instance. With these few metrics you can build a dashboard that tells the whole HA story at a glance: a state timeline of ha_active per instance serves as the deployment roster and shows who is ACTIVE and since when, ha_term shows the current fencing term, and the rate of ha_role_transitions_total per instance works as a flap detector, where 0 means stable and a climbing number means trouble. The project ships exactly such a Grafana dashboard JSON in its repository as a starter. A healthy three-instance deployment shows one ACTIVE, two STANDBY, term 1, and no transitions. After the ACTIVE is killed, the instance on port 2243 took over, the lease term incremented to 2, and its transition counter recorded the promotion; the old ACTIVE rejoined as STANDBY.

Upgrading from the previous release requires one manual step: replication state from 0.9.0 is not compatible with 1.0.0, so operators should run pcsm reset against the target before starting replication with the new version. After that, starting more than one instance is as simple as running the same command on another host: pcsm --source "mongodb://src-mongos:27017" --target "mongodb://tgt-mongos:27017". Check /status on either instance and you will see one ACTIVE and one STANDBY. Kill the ACTIVE and watch the standby pick up replication from the last checkpoint within seconds. Percona invites bug reports, feature suggestions, and code contributions, and points to the PCSM documentation for first-time syncs.

For teams running any long-lived data replication job, the pattern here is transferable.

Also available in: DeutschItalianoShqip