Inside the CRM Sync Orchestrator: How NurtureHub Keeps Your Data Clean Across Every Integration
Inside the CRM Sync Orchestrator: How NurtureHub Keeps Your Data Clean Across Every Integration
Released in v1.0.57
Property agency data lives in a lot of places at once. Your CRM holds the authoritative contact record. NurtureHub holds the engagement history — who opened which email, their intent score, where they sit in a nurture sequence. In a busy lettings or estate agency, both sides of that picture are changing constantly, sometimes simultaneously.
v1.0.57 ships the CRM Sync Orchestrator: the engine that keeps those two worlds in sync without data loss, without duplicates, and without blowing through your CRM provider's API rate limits.
Here is how it works.
Delta Sync with Provider Cursors
Early sync implementations fetch everything every time. That works at low volume, but it doesn't scale — and it creates noise.
The Sync Orchestrator instead tracks a cursor for each connected CRM provider. A cursor is a lightweight bookmark (typically a timestamp or a sequence token, depending on what the provider exposes) that marks the end of the last successful sync window. On the next run, the orchestrator fetches only records that changed after that cursor.
The result: sync cycles stay fast even as your contact database grows, and each cycle touches only the data that actually needs attention.
Cursors are stored per-tenant, per-provider, so a slow sync on one integration never affects another.
Field-Level Conflict Resolution
Bidirectional sync creates a fundamental problem: what happens when the same field is updated in both the CRM and NurtureHub between two sync cycles?
The Sync Orchestrator resolves this at the field level using a clear, deterministic policy:
| Data type | Winner |
|---|---|
| Contact data (name, email, phone, address, status) | CRM |
| Engagement data (email opens/clicks, intent score, nurture sequence state) | NurtureHub |
This policy reflects where each system has genuine authority. Your CRM is the record of truth for who a contact is. NurtureHub is the record of truth for how that contact is engaging. Neither system blindly overwrites the other.
Conflicts detected and resolved are recorded in the sync audit log (see below).
Deduplication
Duplicate contacts are one of the most persistent pain points in any CRM integration. They arise from manual data entry, imports, API errors, and the edge cases that appear when two systems both try to create a record for the same person around the same time.
The Sync Orchestrator runs a multi-field matching strategy before creating any new contact record. If an incoming record matches an existing contact on a combination of identifiers, the orchestrator treats it as the same person and updates rather than creates. Duplicate suppression events are counted and logged per sync cycle.
Idempotent Upserts
All writes — in both directions — are idempotent. If a sync cycle is interrupted and re-run, or if the same data arrives twice, the end state is identical to running it once. There are no double-writes, no doubled engagement records, no phantom sequence enrolments.
This is particularly important during failure recovery. If a sync job fails halfway through, it can be safely retried from the beginning of the same cursor window without any manual cleanup.
Rate-Limited Outbound Batching
Different CRM providers enforce different API rate limits. Pushing a large batch of updates to a provider as a single burst is a reliable way to get throttled — or blocked.
The Sync Orchestrator batches outbound writes and spaces them to stay within each provider's documented limits. Batching is handled automatically; there is nothing to configure on a per-sync basis. The orchestrator knows the constraints for each supported provider (agentOS, Reapit, Alto, Street, Loop) and adapts accordingly.
Sync Audit Log
Every sync cycle produces a structured audit log entry. Each entry records:
- Cursor window — the start and end of the time range processed
- Record counts — contacts fetched inbound, records written outbound
- Conflicts detected and resolved — with field-level detail
- Duplicates suppressed — count of records matched to existing contacts rather than created
- Errors — any provider API errors, with status codes and retry state
The audit log is accessible from the tenant admin area and is the first place to look when diagnosing an unexpected sync outcome.
Scheduled Execution via Inngest
The Sync Orchestrator runs as a scheduled Inngest function. Sync frequency is configured at the tenant level — different agencies can run on different intervals based on their volume and CRM plan.
Because the scheduling is managed by Inngest, intervals can be adjusted without any infrastructure changes. There is no cron job to edit and no deployment required to change a tenant's sync cadence.
What You Need to Do
Nothing. Existing CRM connections automatically pick up delta sync, conflict resolution, deduplication, and the audit log from the next scheduled sync cycle. No re-authorisation, no configuration changes, no disruption to live nurture sequences.
Summary
| Capability | What it does |
|---|---|
| Delta sync | Fetches only changed records using provider cursors |
| Conflict resolution | CRM wins on contact data; NurtureHub wins on engagement data |
| Deduplication | Prevents duplicate contact creation across sync cycles |
| Idempotent upserts | Safe to retry; no double-writes |
| Rate-limited batching | Respects per-provider API limits automatically |
| Audit log | Full per-cycle record of conflicts, duplicates, and errors |
| Scheduled via Inngest | Configurable sync interval per tenant, no infra changes needed |