Every night, only what changed, and nothing lost when a night fails
Your scheduler starts the run. QueryAPIGate takes a lease so two runs never overlap, asks the database for what changed since the last file that landed, and writes it under the one prefix the destination allows. The watermark moves only after the file is written, so a failed night is sent again the next.
run 185 · 2026-10-12 02:001,904 rows · a second run refused
run 186 · 2026-10-13 02:00write failed · watermark stays
run 187 · 2026-10-14 02:004,214 rows · nights 3 and 4 · watermark → 10-13 23:57
watermark
Stablecompatibility promiseExpmay change in a minor releaseTest a destination first: one small probe object, written under its prefix.
Who starts itYour cron, CronJob or AirflowQueryAPIGate doesn't keep a clock; your scheduler runs the export.
↓
Front door StableExportsOne command or one API call runs the published version of a saved query.
↓
The governed coreLease → watermark → stream → write → recordOne run at a time. Only what changed since the last file that landed. Written under the destination's prefix, and only then does the watermark move.
↓
Reads fromYour databaseWHERE updated_at > :since
↓
Writes toTheir bucketAn s3://, gs:// or r2:// prefix; nothing can be written anywhere else.
↓
NightsA failed night is sent againThe watermark stays where it was, and the next run delivers both nights' rows: at least once, never lost.
whocron 02:00doorqueryapigate exports runsince = last watermark ✓one run at a time ✓locked to the prefix ✓datas3://acme-inbound/orders/…parquet
For pipelines and partners' buckets
Deliver a daily file, incrementally, to someone else's bucket
Every night a partner needs yesterday's changes as Parquet in their S3 bucket. Writing that job means credentials, retries, a watermark and a place to see when it failed. A saved export is all of those.
✓A destination is an s3://, gs:// or r2:// prefix with credentials stored like a connection password. Every write is locked to that prefix.
✓Incremental: the largest updated_at delivered last time is bound to :since next run. The watermark moves only after the file is written.
✓One run at a time per export; a crashed run cannot hold the lease forever. The export_failing alert fires while the newest run failed.
✓Scheduling stays with what you have: cron, a Kubernetes CronJob, Airflow.
The example APIs ship with a generated database and one scoped key per scenario, so you can try each of these in a few minutes without connecting anything of your own.