Scheduling
Run a connector on a cron expression in any timezone, control what happens after downtime, and understand the backoff when a source keeps failing.
A connector runs manually, on a fixed interval, or on a cron expression. Cron is the right default for a catalogue: a nightly full sync plus a delta every fifteen minutes during business hours is two rows, not a queue service.
Choosing a schedule
Two fields exist and cronExpr wins when both are set.
schedule | cronExpr | Behaviour |
|---|---|---|
manual | null | Only runs when triggered by hand |
hourly | null | Every 60 minutes from the last run |
daily | null | Every 24 hours from the last run |
| anything | */15 * * * * | Five-field cron evaluated in timezone |
The interval form is anchored to the previous run, so a slow run does not
stack: the next one starts an interval after it finished. Cron is anchored to the
clock, so 0 3 * * * means 03:00 local time whether or not the previous run
took long.
That difference matters. Use cron when the time of day matters — a nightly sync after your ERP closes, a delta that must not overlap business hours. Use an interval when you only care about frequency.
Cron format
Five fields, in this order:
┌───────── minute 0-59
│ ┌─────── hour 0-23
│ │ ┌───── day of month 1-31
│ │ │ ┌─── month 1-12
│ │ │ │ ┌─ day of week 0-6 (Sunday = 0)
│ │ │ │ │
* * * * *| Expression | Meaning |
|---|---|
*/15 * * * * | Every 15 minutes |
0 * * * * | Every hour on the hour |
0 3 * * * | Daily at 03:00 |
0 3 * * 1 | Mondays at 03:00 |
0 2 1 * * | First of the month at 02:00 |
0 9-18 * * 1-5 | Hourly, 09:00–18:00, weekdays |
Cron expressions are validated on save. An invalid one is rejected, not silently disabled — a connector that never runs because of a typo is worse than a clear error.
Timezones
timezone is an IANA name, default UTC:
| Timezone | 0 3 * * * fires at |
|---|---|
UTC | 03:00 UTC |
Europe/Moscow | 03:00 MSK (00:00 UTC) |
America/New_York | 03:00 EST or EDT, wherever DST puts it |
The scheduler resolves the expression in that zone on each tick, so DST transitions behave correctly: a 02:30 job in a zone that skips 02:00–03:00 in spring is handled by the resolver rather than firing twice or never.
Use the zone of the business, not of the server. A "nightly at 03:00" sync in Moscow that runs at 03:00 UTC starts at 06:00 local and still overlaps the morning.
What happens after downtime
If the scheduler is not running — a deploy, an outage, a paused worker — windows
are missed. catchUpPolicy decides:
| Policy | Behaviour |
|---|---|
skip (default) | Fast-forward to the next future window. One run, not N. |
run | Fire once immediately on recovery, then resume the normal schedule. |
skip is the default on purpose. A connector that was down for six hours should
not hammer the source with 24 back-to-back runs — nothing changed in the
meantime, and a burst looks like an attack to whatever is serving the feed.
run suits a source that is itself periodic and cheap to read once, where you
want the current state as soon as possible rather than waiting for the next
window.
A jitter of a few seconds between ticks is never treated as a missed window — only a gap larger than one full period is.
Retry and backoff
A failed run does not retry immediately and does not retry forever.
| Consecutive failures | Next attempt after |
|---|---|
| 1 | 60 s |
| 2 | 2 min |
| 3 | 4 min |
| 4 | 8 min |
| … | doubled, capped at 24 h |
A jitter is added so a fleet of connectors pointing at the same rate-limited API
does not retry in lockstep. failureCount resets to zero on the first successful
run.
After ten consecutive failures the connector is reported for attention — the run history in the console carries the error, and the operator sees a failing connector rather than a silent one.
Preventing overlapping runs
Two triggers can fire the same connector at once: the schedule and a manual "Sync now". The run claims a lease before touching documents; a second claim on a live lease returns "already running" instead of duplicating the work. Without this, two concurrent runs would write the same documents twice and double the metered quota consumption.
If a run dies mid-flight, the lease expires and the next tick recovers the job
rather than leaving it stuck in running.
Recommended setups
Catalogue, 50 000 products, ERP updated during the day
| Field | Value |
|---|---|
cronExpr | */15 * * * * |
timezone | your business zone |
mode | delta |
pruneDeleted | true |
Documentation site, sitemap
| Field | Value |
|---|---|
cronExpr | 0 4 * * * |
mode | full |
pruneDeleted | true |
Daily is enough — documentation does not change every fifteen minutes, and a full run is how a removed page actually leaves the index.
Small export that changes weekly
| Field | Value |
|---|---|
schedule | manual |
mode | full |
Not everything needs a schedule. A connector that runs on deploy is honest about being a deploy step.