When and how a source's data gets refreshed. Three modes —
Full Sync,
Incremental, and
Reconciliation —
answer one question in different ways: take everything, take only the
delta, or reconcile against the source as a whole. The mode selects only
the fetch window (since) and the aggressiveness of entity
resolution; the
pipeline itself is one and
the same for all three. Every mode runs on a background worker — run
durability (SyncRun, checkpoint, DLQ) is held by
reliability.
since from the previous run. The
pipeline sees only the delta — that's cheap and fast. The
mechanics of events and of the since-based
increment are held by
sources.
The two cases below — partial re-sync and dlq retry — aren't
separate modes but the same incremental with a different
trigger and scope; the "type" in the run history is
derived
from this pair, not stored as a separate column.
since — no delta means it was just
quiet, and the pass was for nothing; a delta found is the
missing data. The watchdog then runs an ordinary incremental
with since = incremental_cursor — there's no
separate "re-sync window": the cursor only advances on success,
and
Load is
idempotent, so re-requesting the delta is safe. All without a
full import and without a human. In the run history such a
re-sync is tagged with its own type — a string of them in a row
reads as an unhealthy webhook, not the norm.
since but from the specific identities in the
review queue. Kin to partial_resync — both patch
in a targeted way — but launched manually, after the cause
(permissions, source) is fixed, rather than by the watchdog.
Processed items leave the queue; its mechanics are held by
reliability
and
the data model.
resolve. The
difference is the size of the visibility window, not the logic:
the resolve area is always bounded by what falls into the run's
fetch window. Incremental sees a narrow window by
since → dedup is local only; reconciliation pulls
the source whole in one run and collapses intra-source
duplicates scattered across earlier increments — invisible to
the narrow window. There's no conflict with the pipeline here:
the upsert key
(source_id + source_type + source_entity_id)
covers the same source_entity_id across runs,
while the aggressive resolve works on one entity under
different ids within the visible full source
(cross-source stitching is held by
Knowledge Store). This is a hygiene mode, not a mode for delivering fresh
data.
A mode is always the state of one source, not of the platform. Each
source syncs on its own and holds its own since, its own
schedule, and its own current mode. "Sync everything" isn't a special
shared run but a launch of all per-source syncs at once.
In parallel with delivery runs the platform-level
curation of the graph in Knowledge Store. By default the lanes don't
get in each other's way; only during destructive curation steps (merge,
retention) does the affected source's run go to queued —
mutual exclusion is held by
Knowledge Store · Lane coordination.
When to run Incremental and Reconciliation is set by the schedule: the platform's global default plus a per-source override. A source without its own schedule inherits the shared one; with its own, it follows that.
platform_settings (the same platform-settings table as
timezone; edited from Admin without a deploy). The per-source override
lives in the sync_interval /
reconcile_interval / reconcile_window
fields: NULL = inherit the global default. The
reconciliation window is stored as a minute of the week without a
zone — the scheduler unfolds the hour from the setting in the
org-timezone into a UTC launch moment.
Managing the schedule is UI over the sync backend domain, not part of the pipeline. Both schedules are held by the screens — Admin Panel · incremental and Admin Panel · reconciliation.