Scheduled backups
Quay’s scheduler fires cron entries on a 60s tick. While the desktop app is open, schedules fire on time. For “back this up at 3am whether or not my Mac is open”, install the Quay CLI as a launchd or systemd unit.
Set up a schedule
Section titled “Set up a schedule”Settings → Pro Plus → Scheduled backups → + Add schedule.
| Field | Notes |
|---|---|
| Label | Free-form (e.g. nightly prod pg) |
| Connection | Picked from your existing connections |
| Cron | 5-field cron in UTC (0 3 * * * = daily at 03:00 UTC) |
| Destination | Optional — a cloud backup destination; blank means local-only |
| Enabled | On / off — disabling keeps the row, paused |
Schedules persist to:
| OS | Path |
|---|---|
| macOS | ~/Library/Application Support/com.unclez.quay/schedules.json |
| Linux | ~/.config/quay/schedules.json |
How it fires
Section titled “How it fires”The desktop app polls every 60 seconds. For each enabled schedule:
- Compute “did the cron’s next firing after the last tick fall at or before now?”. If yes, fire.
- Resolve the connection from
connections.json. Skip with a clear status if the connection has been deleted/renamed. - Dispatch to the right dump path:
- PG / MySQL / MariaDB / SQLite / DuckDB / ClickHouse → SQL dump
- MongoDB →
mongo_dump_database(JSONL per collection) - Redis →
redis_dump_keys(JSONL of every key) - Other engines →
skipped: <dialect> not yet supported
- Persist
last_run_at+last_statustoschedules.jsonso the UI list reflects progress.
If a dest_id is set, Quay also uploads to the cloud destination
(S3 / R2 / GCS) after the local dump succeeds. Upload failure
doesn’t fail the schedule — local backup is the source of truth.
24/7 schedules — the CLI
Section titled “24/7 schedules — the CLI”The desktop app’s scheduler ticks only while Quay is running. For “back this up overnight even with my laptop closed”:
- Install Quay CLI (ships pre-built starting v0.3.2)
- Set up the launchd plist (macOS) or systemd unit (Linux)
- Run
quay daemon— it reads the sameschedules.jsonthe desktop app writes, dumps to the same on-disk format, and persistslast_run_atback so the desktop app’s schedule list shows progress when you next open it.
The CLI is stateless. You author schedules in the desktop app’s UI; the CLI just runs them. No separate config file, no separate UI.
Cron expression cheat sheet
Section titled “Cron expression cheat sheet”| Cron | Fires |
|---|---|
0 3 * * * | Daily at 03:00 UTC |
0 * * * * | Every hour, on the minute |
*/15 * * * * | Every 15 minutes |
0 4 * * 0 | Sundays at 04:00 UTC |
0 0 1 * * | Monthly on the 1st at midnight UTC |
*/5 9-17 * * 1-5 | Every 5 minutes during business hours, weekdays |
Times are UTC. Quay doesn’t read system TZ on purpose — schedules stay timezone-stable when you take the laptop across zones, which is the trade-off most users want.
Last-run status conventions
Section titled “Last-run status conventions”The schedule list shows last_status:
| Status | Meaning |
|---|---|
ok: 84 tables, 12,402 rows | Successful dump |
ok: 1,248 keys | Redis dump |
ok: 12,402 documents across 3 collections | Mongo dump |
failed: connection X not found | Connection profile renamed/deleted |
failed: <db error> | Engine-side failure; full message in the row |
skipped: <dialect> not yet supported by … | Engine the daemon doesn’t cover yet |
skipped: no active session | Desktop scheduler only — connection wasn’t open |
File naming + locations
Section titled “File naming + locations”Local dumps land at:
~/Documents/Quay-backups/<sanitized-conn-name>-<UTC-stamp>.<ext><ext> is .sql for the SQL family + .jsonl for Mongo + Redis.
The path is currently hard-coded; the v0.4 release picks it up from
the same “backup default location” setting the desktop app uses
(Settings → Behavior).
Cloud uploads go to whatever object key the destination is configured for; see Cloud backup destinations.
Common patterns
Section titled “Common patterns”- Nightly prod backup, encrypted, to R2: schedule =
0 3 * * *, destination set to an R2 bucket, format.qenc. Combine with the CLI as a launchd unit so the laptop being asleep doesn’t matter. - Hourly Redis cache snapshot: schedule =
0 * * * *, no destination, local-only. JSONL output is grep-able if you need to diagnose state at a specific hour. - Weekly schema-only dump: per-table opt-outs to drop the data — emits CREATE TABLE / VIEW / etc. only, no INSERTs. Useful for documenting schema drift over time.