What you’ll build
A partner integration that:- Receives a Bearer token from the customer during onboarding
- Performs an initial full backfill of all VOMO Users into the external system
- Polls VOMO for ongoing changes and propagates them to the external system
- Reconciles daily to catch gaps and deletions
- Surfaces sync health visibility to the customer
When this recipe fits
Architecture
Six components, each independent — failures in one don’t crash others:Step 1: customer onboarding
The onboarding flow handles three things: capture the Bearer token, configure sync targets, trigger the initial backfill.JavaScript
Why initialize the checkpoint to epoch
Setting the checkpoint tonew Date(0) means the next polling cycle would query “everything updated since 1970” — which is everything. But the backfill runs first; once the backfill completes, the checkpoint advances to the latest-seen timestamp. From that point forward, polling operates incrementally.
This approach unifies backfill and steady-state under one mechanism — no separate code paths.
Step 2: initial backfill
The backfill reads all VOMO Users and pushes them to the external system. For a 10,000-user customer, this is ~667 paginated requests at 15 records per page.JavaScript
What processUserForBackfill does
JavaScript
Backfill duration estimates
Communicate this during onboarding so customers understand the initial sync isn’t instant. Show progress in the UI if available.
Step 3: steady-state polling
After backfill, the polling worker takes over. It runs on a schedule and processes only what’s changed.JavaScript
Why use the mapping table to detect new vs. update
The 200/201 detection works at the VOMO upsert level. Here we’re going the other direction (VOMO → external) — the mapping table is the source of truth for “have we seen this user before in this customer’s integration”:
This is more robust than time-based heuristics (
created_at == updated_at). The mapping table is the integration’s persisted view of reality.
Step 4: daily reconciliation
Daily reconciliation catches gaps and re-processes them. See Reconciliation Patterns for the full pattern.JavaScript
Weekly deletion detection
JavaScript
Step 5: customer-facing visibility
Customers ask “is our integration working?” — build a per-customer dashboard that answers in seconds:JavaScript
Bidirectional sync
Some integrations need to also write back to VOMO — e.g., the external CRM is source-of-truth for user phone numbers.JavaScript
Operational concerns
Token expiration
JavaScript
Customer offboarding
JavaScript
Per-customer rate-limit budgets
JavaScript
Things to watch for
A few subtleties that surface in production:The participation gap
This recipe syncs users but not their participations (since participations don’t advanceupdated_at). For integrations that need participation data, see Detecting User Changes: The participation caveat and add a separate participation-polling layer.
Large customers stress the integration
A 100,000-user customer can produce 5,000 changes per day during active periods. The polling worker handles this through pagination, but downstream processing (writes to external system) is often the bottleneck. Monitor per-customer processing rate and scale workers as needed.Backfill scheduling
For very large customers, the initial backfill can take hours. Schedule it for low-traffic hours and communicate timing to the customer. Prevent multiple workers from picking up the same backfill (use a lock or unique-claim pattern).Mapping table growth
Per-customer mapping tables grow unbounded over time. For multi-tenant integrations:- Periodic archival of long-inactive customers’ mapping tables
- Partitioning by customer for query performance
- Indexes on (customer_id, vomo_user_id) and (customer_id, email)
Dead-letter queue management
The DLQ catches failures but isn’t self-cleaning. Build:- Automatic retry of recoverable failures (timeouts, transient 5xx)
- Manual review queue for unrecoverable failures (data validation, permanent destination errors)
- Aging policies (alert on DLQ entries older than N days)
What you’ve built
After this recipe:- ✅ Onboarding flow that captures and validates the Bearer token
- ✅ Initial backfill that mirrors all VOMO users to the external system
- ✅ Polling worker that catches incremental changes every 15-30 minutes
- ✅ Daily reconciliation catching gaps
- ✅ Weekly deletion detection
- ✅ Per-customer dashboards showing sync health
- ✅ Operational handling for token failures, offboarding, and rate budgets
Where to go next
Build a Group from a Query
Build Groups dynamically from query results.
Report on Volunteer Hours
The reporting recipe using participation data.
Reconciliation Patterns
The reconciliation patterns this recipe references.
Sync Architecture Patterns
The broader architectural patterns for sync designs.