Skip to main content
Polling catches most changes — but not all. Some events slip through the gaps:
  • Deletions don’t appear in updated_after queries (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
Reconciliation is the answer to all of these. It’s a separate, slower-cadence process that audits actual state against expected state and catches the gaps. Combined with polling, it produces production-grade reliability that polling alone cannot. This page covers the reconciliation patterns: daily and weekly cadences, deletion detection, three-way state checks, and the per-customer orchestration that makes reconciliation work at scale. If you haven’t yet, skim the Polling Overview for the polling foundation that reconciliation complements.

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 pattern is the same regardless of resource (Users, Projects, Groups, etc.). The specifics differ — what fields to compare, what corrective actions are appropriate — but the structure stays consistent.

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:
For larger customers, consider weekly cadences and off-peak scheduling.

Distinguishing deletion from inaccessibility

A user “missing” from the list query could mean: The detail fetch (GET /users/{id}) resolves the ambiguity:
  • 200 response → user exists but didn’t match list query (investigate filters)
  • 404 response → user is truly gone
Without the detail-fetch step, you’d propagate “deletions” for users who actually just changed scope — confusing the external system.

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
Cost: Bounded by the daily change volume. Typical: a few hundred records per day per customer. Manageable.

Full (weekly) reconciliation

Re-reads everything. Higher cost, catches everything including deletions and drift.
JavaScript
Cost: Full dataset read each run. Expensive — schedule during off-peak hours.

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
This runs on a tighter cadence than other reconciliation (every few hours for active customers) because participation freshness matters more for downstream workflows.

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
For 60 customers, this spreads reconciliation across an hour. The total elapsed time is the same, but no minute has all 60 customers’ reconciliation running simultaneously.

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
The cadence becomes per-customer configuration, tuned to actual activity.

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
For customer-facing transparency, this audit trail is valuable:
JavaScript
Customers asking “is our sync working?” get a definitive answer backed by audit data.

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
These practices catch the residual failures that polling misses — turning a “mostly works” integration into one that’s auditable, debuggable, and trustworthy.

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.
Last modified on May 22, 2026