- Deletions don’t appear in
updated_afterqueries (the record is just gone) - Silent processing failures advance the checkpoint despite the change not being applied
- Field changes that don’t advance
updated_at(rare but possible) - Worker crashes mid-batch that fail to track which records were processed
- External-system writes that fail asynchronously — the integration thought it succeeded but didn’t
What reconciliation does
A reconciliation pass:1
Reads the actual current state from VOMO
Typically a full or windowed list of a resource.
2
Reads the expected state from your integration's external store
What you believe VOMO contains based on prior sync activity.
3
Computes the diff
Records in VOMO but not in your store (missed creates / updates), records in your store but not in VOMO (missed deletions), records with mismatched fields (drift).
4
Applies corrective actions
Re-process missed records, mark deletions in downstream systems, alert on unexplained drift.
5
Records the reconciliation result
For monitoring, audit trail, and capacity planning.
The minimum reconciliation: daily catch-up
The simplest useful reconciliation: every night, re-read yesterday’s changes and verify they were processed.JavaScript
What this catches
What this doesn’t catch
For most production needs, daily catch-up reconciliation closes 90%+ of the gaps that polling misses. The remaining gaps require more comprehensive patterns.
Deletion detection
Deletions are the hardest thing to detect in a polling architecture. The pattern: periodically read the full current state, compare to what your external store thinks exists, and treat the difference as deletions.The full-state scan
JavaScript
Run cadence
Deletion scans are full-dataset operations — expensive in API requests. Pace accordingly:
Distinguishing deletion from inaccessibility
A user “missing” from the list query could mean:
The detail fetch (
GET /users/{id}) resolves the ambiguity:
200response → user exists but didn’t match list query (investigate filters)404response → user is truly gone
Three-way state reconciliation
The most rigorous pattern: compare three sources of truth. Each pair has a possible disagreement:The end-to-end audit
JavaScript
When to run end-to-end audits
For partner integrations serving customers with strict data correctness needs (compliance reporting, audited financials), random sampling at 1% weekly catches most drift before it becomes a customer-facing issue.
Incremental vs. full reconciliation
Two distinct cadences for different purposes:Incremental (daily) reconciliation
Re-reads a recent time window. Lower cost, catches recent gaps.JavaScript
Full (weekly) reconciliation
Re-reads everything. Higher cost, catches everything including deletions and drift.JavaScript
Combining the two
For most production integrations, both cadences run: Different cadences catch different issue classes; the layered approach catches more than any single pass.Per-resource reconciliation patterns
Different resources have different reconciliation needs:Users
Projects
Groups
Forms / Form Completions
Participation reconciliation (the hardest case)
Because participations aren’t directly polled, reconciliation is the only path. Run daily:JavaScript
Per-customer orchestration
For partner integrations serving many customers, reconciliation across them needs orchestration:JavaScript
Staggering
Avoid running reconciliation for all customers at the same minute — spike load and rate-limit hits will follow. Stagger:JavaScript
Per-customer cadence
Not every customer needs the same cadence. Small customers (a few hundred users) might be fine with weekly full reconciliation; large customers (50,000+ users) need daily.JavaScript
Reconciliation as documentation
A useful side-effect of reconciliation: it produces an audit trail. Each reconciliation run records:- When it ran
- What it checked
- What gaps it found
- What corrective actions it took
- Whether the integration is operating correctly
JavaScript
When reconciliation finds too much
A successful reconciliation finds zero gaps. A few gaps per day is normal. A sudden spike in gaps means something is wrong with polling:
Treat reconciliation results as a signal for investigation, not just automatic correction. If gaps grow, pause auto-correction until the root cause is understood.
Production checklist
For reconciliation:- Daily incremental reconciliation per resource per customer
- Weekly full reconciliation including deletion detection
- Three-way audits (sample-based) at least weekly
- Reconciliation is throttled — doesn’t compete with regular polling
- Per-customer cadence is configurable, not hardcoded
- Staggered scheduling avoids same-minute spikes
- Audit trail of every reconciliation run is preserved
- Per-customer “sync health” view exposes the data
- Alerts fire when gap rate exceeds threshold (e.g., >1% daily)
- When reconciliation finds too much, pause auto-correction and surface for review
Where to go next
Change Detection Best Practices
The cross-cutting reliability patterns: checkpointing, idempotency, drift detection.
Sync Architecture Patterns
The broader architectural picture for sync designs.
Detecting User Changes
The polling pattern that reconciliation complements.
Detecting Project Changes
Same for Projects, including the schedule-diff pattern.