Resume MongoDB Change Streams Without Missing Events
Store resume tokens durably so your application can resume MongoDB change streams after restarts without missing events.
17 Jul 2025, 05:16 UTC

The problem: a restarted watcher misses what happened while it was down
Your service uses a MongoDB change stream to react to inserts, updates, replaces, and deletes. The stream works until the service restarts. When the driver reconnects and calls watch() again with no resume point, MongoDB starts sending only new operations. Anything written during the outage is never delivered. If your downstream process depends on every change—updating a search index, invalidating a cache, or forwarding events to another system—that gap is a bug.
The useful takeaway: store each change stream's resume token durably, and pass it back to watch() when the driver reconnects. MongoDB then resumes from the last known oplog position instead of starting from now.
What a resume token is
A resume token is an opaque document returned with every change event. It encodes a position in the replica set oplog, the operation log where MongoDB records writes. Passing the token from the most recent event tells the driver where to continue. Tokens are supported on replica sets and sharded clusters with replica sets, using the WiredTiger storage engine, starting in MongoDB 3.6. Standalone mongod instances do not support change streams.
Worked example: store and reuse a token
First confirm the deployment topology. Run this in mongosh connected to a replica set member:
rs.status()
Required permissions: a role such as clusterAdmin or hostAdmin. Expected check: the output contains a members array and members report PRIMARY or SECONDARY. Risk: running this on a standalone returns an error or empty replica set status, which means change streams are not available.
Also confirm the server version:
db.version()
Required permissions: any authenticated user. Expected check: a version string such as 7.0.x. The fullDocumentBeforeChange pre-image option requires MongoDB 6.0 or later.
In your application code, keep the last token in durable storage—your database, a key-value store, or a file—not only in memory. Here is a Node.js driver pattern using a placeholder for your stored token:
const { MongoClient } = require('mongodb');
async function watchCollection(storedToken) {
const client = new MongoClient('mongodb://localhost:27017');
await client.connect();
const collection = client.db('inventory').collection('products');
const changeStream = collection.watch([], {
fullDocument: 'updateLookup',
resumeToken: storedToken
});
changeStream.on('change', (event) => {
await processEvent(event);
await saveToken(event.resumeToken);
});
}
Placeholders: replace mongodb://localhost:27017 with your replica set connection string, and storedToken with the token retrieved from your durable store. If no token exists yet, omit resumeToken to start from the current time.
Risk: if saveToken fails after processEvent succeeds, the next restart may reprocess the same event. Design processEvent to be idempotent, or save the token before processing and accept possible missed events on crash.
Limitations and how to verify
- Change streams are not a general-purpose audit log. If the resume token is lost, or if the oplog recycles the entry the token points to, the stream cannot resume and must restart from the present.
- High write volume can increase lag and memory pressure on the change stream cursor.
- Standalone deployments are unsupported; use a replica set even for development.
Practical verification: insert a document into the watched collection, open a change stream with a stored token, then restart the driver and pass the last token again. Confirm the driver receives operations written after the token and does not require a full collection rescan. Do not treat this as a production audit trail without testing token loss and failover behavior.
Closing
MongoDB change streams remove the need to poll the oplog yourself, but only if you manage the resume point. Treat the resume token as part of your application state: save it durably, restore it on reconnect, and verify the topology and version before you rely on it.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.