Change Stream Sync
Overview
Change Stream sync uses MongoDB's native Change Stream mechanism to dispatch accepted data-change events to one or more targets. It is useful for backup databases, denormalized projections, cache invalidation callbacks, and other asynchronous CDC workflows.
Core Features
- ✅ Asynchronous CDC: Based on MongoDB Change Stream; latency depends on MongoDB, network, and target workload
- ✅ Decoupled design: Primary database writes do not wait for target apply callbacks
- ✅ Resume breakpoint: Resume Token is saved after all matching targets succeed, so restarts can resume from the latest persisted token
- ✅ Multi-target support: Sync to multiple backup databases at the same time
- ✅ Data Filtering: Custom filtering logic
- ✅ Data conversion: Support desensitization and field conversion
- ✅ Observable lifecycle: Sync stats expose running state and error counters for monitoring/restart workflows
- ✅ Health Check: Target health-check configuration for managed targets
⚠️ Prerequisites
Must satisfy
-
MongoDB Replica Set 🔴
-
MongoDB version >= 4.0 🔴
-
User Permissions 🔴
🚀 Quick Start
Basic configuration
📖 Configuration options
sync configuration
transform is a manager-level conversion hook. It runs once for each accepted change event before the event is delivered to all matching targets, so all targets receive the same transformed document. Delete events usually do not include fullDocument; custom targets should handle an undefined document and use event.documentKey for delete handling.
targets[].Configuration
resumeToken configuration
Resume token persistence is strict by default. File storage writes to a same-directory temporary file, fsyncs it, keeps the previous token as <path>.bak, and then atomically renames the temporary file into place. Startup also validates the stored token: a corrupted token fails fast when strictLoad is true, instead of silently starting without a resume token. After all eligible targets apply an event successfully, monSQLize saves the event resume token; syncedCount advances only after that save succeeds. If token persistence fails after the configured retries, or any eligible target fails to apply the event, the manager records the error, closes the live stream, marks isRunning: false, and does not process later queued events. This is an at-least-once contract, not exactly-once: a crash after target apply and before token save can replay the same event. Set strictSave: false and strictLoad: false only for legacy best-effort token-storage behavior, where a restart may replay already-applied events or start without the previously stored token. Built-in MongoDB targets are idempotent (replaceOne(..., { upsert: true }) / deleteOne()); custom apply targets should still deduplicate by change event _id.
idempotency configuration
sync.idempotency is optional and disabled by default. When enabled, the manager builds a per-target idempotency key from the change event _id unless keyBuilder is provided. If the key is already present, that target is skipped and the event can still advance its resume token after all eligible targets are accounted for. Use a durable store for restart protection; the built-in memory fallback only protects repeated delivery in the same process. markMode: 'success' records after apply resolves. markMode: 'start' records before apply; it narrows unknown-success duplicate risk, but a failure after the marker is written can make runtime replay skip that target, so use it only when the target has its own durable idempotency and recovery path.
💡 Usage example
Example 1: Multiple backup targets
Example 2: Data filtering
Example 3: Data desensitization
Example 4: Redis Resume Token
📊 Performance impact
🔧 API
Get statistics
Manually stop synchronization
Manually start synchronization
❓ FAQ
Q1: Prompt "Change Stream is not available"
Reason: MongoDB is not a Replica Set
Solution:
Q2: Is there a delay in synchronization?
Cause: Network delay, backup database performance
Solution:
- Check network delay:
ping backup-host - Check backup database performance:
db.serverStatus() - Reduce the number of synchronized collections
Q3: What should I do if the Resume Token is lost?
Impact: After restarting, synchronization starts from the current time and intermediate data is lost.
Solution:
- Use Redis to store Resume Token
- Back up the Resume Token file regularly
- Manually synchronize all data once
Q4: How to deal with synchronization failure?
Automatic processing:
- Targets that already applied the event are not rolled back, but any target failure stops the manager before the resume token advances
- A resume-token save failure stops the sync manager before the token can advance
- Change Stream driver errors and unexpected stream closes are logged and reflected in stats; monitor
isRunning,errorCount, andlastError, then restart the manager or runtime from your supervisor when needed
Manual processing: