Skip to content

Instantly share code, notes, and snippets.

@alexbevi
Last active August 18, 2025 20:54
Show Gist options
  • Save alexbevi/fc4f59621aee4efbae2c04187dcbf2c6 to your computer and use it in GitHub Desktop.
Save alexbevi/fc4f59621aee4efbae2c04187dcbf2c6 to your computer and use it in GitHub Desktop.
MongoDB 5.0+ Initial Sync Progress Monitoring
/*
* measureInitialSyncProgress
* @author Alex Bevilacqua <[email protected]>
* @updated 2021-02-23
*
* Can be run against a MongoDB 4.2.12+ mongod that is in STARTUP2 (intitial sync) state to gain some
* insight into how the sync is progressing based on the improvements introduced with SERVER-47863.
* For versions of MongoDB < 4.2.12, see https://www.alexbevi.com/blog/2020/02/13/mongodb-initial-sync-progress-monitoring
*
* usage:
* mongo --quiet --eval "load('measureInitialSyncProgress.js'); measureInitialSyncProgress();"
* // pass a value in milliseconds to measureInitialSyncProgress to override the refresh interval
* // default: 5000 (5 seconds)
* mongo --quiet --eval "load('measureInitialSyncProgress.js'); measureInitialSyncProgress(1000);"
*/
function msToTime(duration) {
var milliseconds = parseInt((duration % 1000) / 100),
seconds = Math.floor((duration / 1000) % 60),
minutes = Math.floor((duration / (1000 * 60)) % 60),
hours = Math.floor((duration / (1000 * 60 * 60)) % 24);
hours = (hours < 10) ? "0" + hours : hours;
minutes = (minutes < 10) ? "0" + minutes : minutes;
seconds = (seconds < 10) ? "0" + seconds : seconds;
return hours + ":" + minutes + ":" + seconds + "." + milliseconds;
}
var getReadableFileSizeString = function (fileSizeInBytes) {
var i = -1;
var byteUnits = [' kB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
do {
fileSizeInBytes = fileSizeInBytes / 1024;
i++;
} while (fileSizeInBytes > 1024);
return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i];
};
function measureSyncProgress(previousResults) {
var cmd = db.adminCommand({ replSetGetStatus: 1, initialSync: 1 });
if (!cmd.hasOwnProperty("initialSyncStatus")) {
print("Node not currently performing an initial sync");
return { exit: true };
}
var status = cmd.initialSyncStatus;
db.adminCommand({ replSetGetStatus: 1, initialSync: 1 }).initialSyncStatus.approxTotalBytesCopied
var now = new Date();
var started = status.initialSyncStart;
var approxTotal = status.approxTotalDataSize;
var approxCopied = status.approxTotalBytesCopied;
var message = "Cloned " + getReadableFileSizeString(approxCopied) + " of " + getReadableFileSizeString(approxTotal) + " in " + msToTime(now - started);
if (previousResults !== undefined && previousResults.hasOwnProperty("refreshIntervalMS") !== null && previousResults.hasOwnProperty("copied")) {
var refreshInterval = previousResults.refreshIntervalMS / 1000;
var intervalProgress = approxCopied - previousResults.copied;
if (intervalProgress == 0) {
message += " (No progress in past " + refreshInterval + " second(s))";
} else {
var rate = intervalProgress / refreshInterval;
// We no longer have to calculate remaining ourselves as SERVER-53017 has fixed remainingInitialSyncEstimatedMillis
// var remaining = msToTime(((approxTotal - approxCopied) / rate) * 1000);
message += " (" + getReadableFileSizeString(intervalProgress) + " in past " + refreshInterval;
message += " second(s)) at a rate of " + getReadableFileSizeString(rate) + "/second - ";
message += msToTime(status.remainingInitialSyncEstimatedMillis) + " to go!";
}
}
print(message);
return { copied: approxCopied };
}
function measureInitialSyncProgress(refreshIntervalMS) {
var dbver = db.version().split('-')[0];
if (dbver < "4.2.12") {
print("MongoDB 4.2.12 or greater required but found MongoDB " + dbver);
print("For previous versions see https://www.alexbevi.com/blog/2020/02/13/mongodb-initial-sync-progress-monitoring/");
return;
}
if (refreshIntervalMS === undefined || refreshIntervalMS === null) {
refreshIntervalMS = 5000;
}
var result = measureSyncProgress(result);
result["refreshIntervalMS"] = refreshIntervalMS;
while (!result.exit) {
sleep(refreshIntervalMS);
result = measureSyncProgress(result);
result["refreshIntervalMS"] = refreshIntervalMS;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment