Publish events via the Cloudflare queue → POST /internal/sync-trigger.
Sync-now from the Designer extension.
Per-mapping cron — the hourly scheduler tick.
Dead-letter messages re-posted every 5 minutes.
Destructive rebuild. Needs a 5-min HS256 confirmation token from the cost-preview endpoint, plus a 5-min per-mapping cooldown.
Queued. A lockKey partial-unique index (status pending / in_progress) collapses duplicate triggers.
Claimed atomically by the worker (findOneAndUpdate, 1.5 s poll); heartbeats while running.
Terminal. Counters + lastSynced persisted.
attempts < 5: back to pending with backoff.
attempts = 5: parked, surfaced as needs-attention in the extension.
Terminal, user-initiated.
7 values — webflow_4xx · webflow_5xx · algolia_4xx · algolia_5xx · timeout · validation · unknown. Attached to sync_failed PostHog events, not persisted on the job document.
sync_started · sync_completed · sync_failed · sync_cancelled · queue_dlq_landed.
Stale site · stale Algolia key · sync failures — 7-day per-alert cooldown.
deriveHealth() maps job + mapping state to 7 RowHealth values: syncing · synced · stale · retrying · needs-attention · never-synced · not-mapped.
A message that failed delivery 5 times moves to webflow-sync-dlq; swept every 5 minutes back into POST /internal/sync-trigger.
A job that failed processing 5 times parks as status dead_letter; recovered via manual sync or force-reindex.