Skip to content

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.

Settings → Pro Plus → Scheduled backups → + Add schedule.

FieldNotes
LabelFree-form (e.g. nightly prod pg)
ConnectionPicked from your existing connections
Cron5-field cron in UTC (0 3 * * * = daily at 03:00 UTC)
DestinationOptional — a cloud backup destination; blank means local-only
EnabledOn / off — disabling keeps the row, paused

Schedules persist to:

OSPath
macOS~/Library/Application Support/com.unclez.quay/schedules.json
Linux~/.config/quay/schedules.json

The desktop app polls every 60 seconds. For each enabled schedule:

  1. Compute “did the cron’s next firing after the last tick fall at or before now?”. If yes, fire.
  2. Resolve the connection from connections.json. Skip with a clear status if the connection has been deleted/renamed.
  3. 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
  4. Persist last_run_at + last_status to schedules.json so 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.

The desktop app’s scheduler ticks only while Quay is running. For “back this up overnight even with my laptop closed”:

  1. Install Quay CLI (ships pre-built starting v0.3.2)
  2. Set up the launchd plist (macOS) or systemd unit (Linux)
  3. Run quay daemon — it reads the same schedules.json the desktop app writes, dumps to the same on-disk format, and persists last_run_at back 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.

CronFires
0 3 * * *Daily at 03:00 UTC
0 * * * *Every hour, on the minute
*/15 * * * *Every 15 minutes
0 4 * * 0Sundays at 04:00 UTC
0 0 1 * *Monthly on the 1st at midnight UTC
*/5 9-17 * * 1-5Every 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.

The schedule list shows last_status:

StatusMeaning
ok: 84 tables, 12,402 rowsSuccessful dump
ok: 1,248 keysRedis dump
ok: 12,402 documents across 3 collectionsMongo dump
failed: connection X not foundConnection 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 sessionDesktop scheduler only — connection wasn’t open

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.

  • 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.