Replicate from one source to multiple targets¶
Version added: 0.10.0
You can run multiple Percona ClusterSync for MongoDB (PCSM) instances against the same source cluster and replicate different namespaces to different target clusters at the same time. This lets you split one cluster across several destinations in a single pass, with each instance moving only the data you assign to it.
How it works¶
Each PCSM instance has:
- The same source cluster
- A different target cluster
- Its own namespace filter
Every instance runs the full replication workflow on its own: clone, replication, and finalization. See How PCSM works for what happens at each stage.
Note
Run each PCSM server in a separate container or host, or assign a unique --port when servers share a network namespace. Run every start, status, and finalize command in the corresponding container or host; for a shared host, pass that instance’s --port to every subcommand. The examples below assume separate environments, where all instances can use the default port 2242. See Percona ClusterSync for MongoDB startup configuration for the available options.
Before you begin¶
Map out which instance owns which namespaces and which target before you start. You need that mapping again for every command you run, and it is the only record of which instance owns which data.
Starting replication overwrites target collections
pcsm start drops and recreates the collections that match your filter on the target, discarding any data already in them. Collections outside the filter stay as they are. Review each filter first, since a mistyped pattern affects only the target and leaves no trace on the source.
The examples below replicate db_0 to the first target and db_1 to the second. Select the tab that matches your deployment.
Replicate from a replica set to two targets¶
This example uses a source replica set rs1 and two target replica sets, rs2 and rs3.
| PCSM instance | Source | Target | Included namespaces |
|---|---|---|---|
| csync-a | rs1 | rs2 | db_0.* |
| csync-b | rs1 | rs3 | db_1.* |
Follow these steps:
-
Start
csync-awithrs1as the source andrs2as the target:pcsm \ --source "mongodb://csync:<password>@rs101:27017,rs102:27017,rs103:27017/?replicaSet=rs1" \ --target "mongodb://csync:<password>@rs201:27017,rs202:27017,rs203:27017/?replicaSet=rs2" -
Start
csync-bagainst the same source, withrs3as the target:pcsm \ --source "mongodb://csync:<password>@rs101:27017,rs102:27017,rs103:27017/?replicaSet=rs1" \ --target "mongodb://csync:<password>@rs301:27017,rs302:27017,rs303:27017/?replicaSet=rs3" -
Start replication on
csync-a, filtered to the namespaces it replicates:pcsm start --include-namespaces="db_0.*"Expected output
{ "ok": true } -
Start replication on
csync-bwith its own filter:pcsm start --include-namespaces="db_1.*"For information on how include and exclude filters interact, see Start the filtered replication. For the full flag list, see PCSM commands. You can also drive every step through the PCSM HTTP API.
-
Check each instance and wait for the clone to complete and replication lag to reach an acceptable value. Look for
initialSync.completedset totrueand a lowlagTimeSeconds:pcsm status -
Finalize each instance. PCSM stops replication, creates the remaining indexes on the target, and exits:
pcsm finalizeFinalization cannot be undone
You cannot resume an instance after you finalize it. Running
startagain begins a fresh initial sync and overwrites the target collections a second time. For a migration cutover, stop application writes to the namespaces the instance owns, wait forlagTimeSecondsto reach0, and finalize only then. Instances you are not cutting over yet keep replicating and are unaffected. -
Check the status of each instance after finalization. The following output is from
csync-a. Thecsync-boutput has the same structure with its own operation time and finalization timestamps:pcsm statusExpected output
{ "ok": true, "state": "finalized", "info": "Finalized", "lagTimeSeconds": 0, "eventsRead": 0, "eventsApplied": 0, "lastReplicatedOpTime": { "ts": "1787298593.1", "isoDate": "2026-08-21T07:49:53Z" }, "initialSync": { "estimatedCloneSizeBytes": 9877780, "clonedSizeBytes": 9877780, "completed": true, "cloneCompleted": true }, "finalization": { "completed": true, "startedAt": "2026-08-21T07:49:53.633159569Z", "completedAt": "2026-08-21T07:49:53.759444616Z" } }
If the finalization object contains an unsuccessfulIndexes array, review it before you send traffic to that target. See Unsuccessful indexes.
Verify the result on replica set targets¶
Connect to each target and confirm it holds only the namespaces that its instance replicated.
show databases
You see db_0 next to admin, config, and percona_clustersync_mongodb, which is where PCSM keeps its own replication metadata. The db_1 database is absent, because csync-a never replicated it.
Counting documents confirms the same thing from the data side:
db.getSiblingDB('db_0').docs.countDocuments({})
db.getSiblingDB('db_1').docs.countDocuments({})
The first count matches the source. The second returns 0 rather than an error,
PCSM recreates the source indexes on the target during finalization, so check that they arrived:
db.getSiblingDB('db_0').docs.getIndexes().map(i => i.name)
Expected output
[
'_id_',
'value_1',
'value_1_uid_-1',
'uid_1',
'tag_text',
'_id_hashed',
'created_at_1',
'value_partial',
'tag_sparse'
]
The collection replicated to the other target does not exist here, so querying it returns an error.
db.getSiblingDB('db_1').docs.getIndexes().map(i => i.name)
MongoServerError[NamespaceNotFound]: ns does not exist: db_1.docs
Repeat the same three checks on rs3 with the databases reversed. There, db_1 holds the data and its indexes, and db_0.docs returns ns does not exist: db_0.docs.
Technical preview
Sharding support in PCSM is a technical preview and is not recommended for production. See Sharding support in Percona ClusterSync for MongoDB.
Replicate from a sharded cluster to two targets¶
This example uses three sharded clusters, each with its own mongos , config server, and two shards. One cluster is the source and two are targets.
| PCSM instance | Source | Target | Included namespaces |
|---|---|---|---|
| csync-a | mongos1 | mongos2 | db_0.* |
| csync-b | mongos1 | mongos3 | db_1.* |
Requirements for sharded deployments
The source and both targets must be sharded clusters running the same MongoDB version, unless you are using cross-version replication. You do not need to disable the balancer on any of them. See Sharding support in Percona ClusterSync for MongoDB.
PCSM connects through mongos on both the source and the target, so you do not need to list individual shard members or config servers in the connection strings.
-
Start
csync-aagainst the sourcemongosand the first targetmongos:pcsm \ --source "mongodb://csync:<password>@mongos1:27017" \ --target "mongodb://csync:<password>@mongos2:27017" -
Start
csync-bagainst the same sourcemongosand the second targetmongos:pcsm \ --source "mongodb://csync:<password>@mongos1:27017" \ --target "mongodb://csync:<password>@mongos3:27017" -
Start replication on
csync-a:pcsm start --include-namespaces="db_0.*"Expected output
{ "ok": true }Before the clone begins, PCSM checks which of the selected collections are sharded on the source and creates matching sharded collections on the target, carrying over the shard key.
-
Start replication on
csync-b:pcsm start --include-namespaces="db_1.*"For information on how include and exclude filters interact, see Start the filtered replication. For the full flag list, see PCSM commands. You can also drive every step through the PCSM HTTP API.
-
Check each instance and wait for the clone to complete and replication lag to reach an acceptable value. Look for
initialSync.completedset totrueand a lowlagTimeSeconds:pcsm status -
Finalize each instance:
pcsm finalizeFinalization cannot be undone
You cannot resume an instance after you finalize it. Running
startagain begins a fresh initial sync and overwrites the target collections a second time. For a migration cutover, stop application writes to the namespaces the instance owns, wait forlagTimeSecondsto reach0, and finalize only then. -
Check the status of each instance after finalization. The following output is from
csync-a:pcsm statusExpected output
{ "ok": true, "state": "finalized", "info": "Finalized", "lagTimeSeconds": 2, "eventsRead": 6, "eventsApplied": 5, "lastReplicatedOpTime": { "ts": "1787301347.3", "isoDate": "2026-08-21T08:35:47Z" }, "initialSync": { "estimatedCloneSizeBytes": 9877780, "clonedSizeBytes": 9877780, "completed": true, "cloneCompleted": true }, "finalization": { "completed": true, "startedAt": "2026-08-21T08:35:47.949454942Z", "completedAt": "2026-08-21T08:35:48.21823288Z" } }
Verify the result on sharded targets¶
Connect to the mongos of each target cluster, not to the shards directly. On mongos2, list the databases:
show databases
Expected output
admin 172.00 KiB
config 2.11 MiB
db_0 31.56 MiB
percona_clustersync_mongodb 168.00 KiB
Count the documents. The db_0 database returns the full count and db_1 returns zero:
db.getSiblingDB('db_0').docs.countDocuments({})
db.getSiblingDB('db_1').docs.countDocuments({})
Check that the indexes PCSM recreated during finalization are present:
db.getSiblingDB('db_0').docs.getIndexes().map(i => i.name)
Expected output
[
'_id_',
'value_1',
'value_1_uid_-1',
'uid_1',
'tag_text',
'_id_hashed',
'created_at_1',
'value_partial',
'tag_sparse'
]
The collection replicated to the other target does not exist here, so querying it returns an error. This is the expected result:
db.getSiblingDB('db_1').docs.getIndexes().map(i => i.name)
MongoServerError[NamespaceNotFound]: ns does not exist: db_1.docs
If the source collection was sharded, confirm that the target collection is sharded too.
Chunk distribution differs by design
PCSM replicates data, not sharding metadata. The shard key comes across, but chunk distribution and the primary shard are decided by the target cluster and its balancer, so they will not match the source. A different layout here is expected and does not indicate a problem. See Chunk distribution.
Run the same checks on mongos3 with the databases reversed. There, db_1 holds the data and its indexes, and db_0.docs returns ns does not exist: db_0.docs.
Check the logs¶
Every instance logs separately, so check each one for errors before you decommission the source or send traffic to a target. Command responses go to stdout and logs and errors go to stderr. See Logging in Percona ClusterSync for MongoDB.
If an instance stops because of lost connectivity or a similar failure and you have not finalized it yet, bring it back with pcsm resume --from-failure. See Resume the replication and the Troubleshooting guide.
Next steps¶
Created: September 8, 2026