Recipe: Scheduled Data Sync
This recipe keeps a local table in step with an external API on a timer. A schedule fires on a cron cadence, an http element pulls the latest data from the upstream service, and a sql element absorbs it — inserting new rows and updating changed ones. Your copy of the data stays fresh without anyone refreshing it.
The problem it solves
You depend on data that lives somewhere else — a CRM, a pricing feed, an inventory API — and you need a current local copy to query, join, and build on. Calling the API live on every request is slow and rate-limited; copying it once goes stale immediately. This recipe syncs on a schedule: the data is local and fast to read, and a timer keeps it from drifting out of date.
Elements
| Element | Role |
|---|---|
schedule | Fires the sync on a cron cadence. |
http | Pulls the latest data from the upstream API. |
sql | The local copy — insert new rows, update changed ones. |
automation | Sequences fetch → upsert as one flow. |
Flow
- Create a
schedule. Setspec.cronto your sync cadence; it emits a schedule event downstream each time it fires. Usetrigger_nowto force an immediate sync while testing andnext_runsto confirm the upcoming fire times. - Fetch the upstream data with an
httpelement’srequestoperation (canonical aliascall) — an outbound GET to the API, returning the current payload. - Land it in a
sqlelement.insertrows that are new;updaterows that changed (match on the upstream’s stable id). Shape the table once withmigrate, and read the synced data back withquery. - Sequence the two steps with an
automation, which referencesschedule,http, andsqlas steps — the schedule event triggers the run, the http step fetches, and the sql step writes. Aconditionchild can skip the write when the upstream returned nothing new. - Confirm it is running from the schedule’s
history— a record of every sync, so a stalled feed is visible rather than silent.
What this shows
Each concern is a separate element doing its one job: the schedule owns the cadence, the http element owns the outbound fetch, and the sql element owns the durable local copy with explicit insert/update semantics. Because the trigger is declarative, changing “hourly” to “every five minutes” is one cron edit, and the sync’s history makes reliability observable. The pattern generalizes: point the http step at a different API or the sql step at a different schema and the same skeleton syncs anything on a timer.