Zero external CLI dependencies
A locked architectural rule: no Quay feature requires an external
CLI binary on $PATH to function.
Why this matters
Section titled “Why this matters”Database clients that shell out to mysqldump / pg_dump /
mongodump look elegant in code reviews — “we just call the official
tool”. In practice they create a fragile UX:
- “Quay says I need to install pg_dump” — first-launch papercut
- Wrong version mismatch between client and server — silent broken dumps
- macOS Homebrew ↔ Apple Silicon Rosetta path confusion — random ENOENTs
- Corporate machines where Homebrew + apt are blocked
- New engines (BigQuery, Snowflake, vector DBs) that don’t have a canonical CLI to shell to
So Quay’s rule: every feature must be fully functional with only the Quay binary installed. Everything ships native, written in Rust against the engine’s wire protocol.
What “native” means in practice
Section titled “What “native” means in practice”| Feature | Native implementation | What mysqldump-style would do |
|---|---|---|
| SQL dump | pg_export.rs / mysql_export.rs walk system catalogs + write SQL grammar from scratch | Shell to pg_dump / mysqldump |
| Schema diff | Native catalog walk + per-column comparison | Shell to pg_dump --schema-only × 2 + diff output |
| Streaming import | pg_import.rs / etc. parse statements, stream 1 MB chunks | Shell to psql / mysql |
| Mongo dump | mongo_dump_database.rs walks collections + JSONLs each | Shell to mongodump |
| Redis dump | redis_dump_keys.rs does KEYS * + GET per key | Shell to redis-cli --rdb |
| ER diagram | Native graph layout + SVG/PNG render | n/a |
Optional fast paths
Section titled “Optional fast paths”A few engines have CLI tools that genuinely outperform native
implementations for specific workloads — mongodump for hundreds of
GB, pg_dump --format=directory for parallel dumps. Quay supports
those as optional fast paths:
- The native path is the default
- If the CLI is detected (which path), an “Use mongodump for large dumps” toggle appears in the export dialog
- Selecting it shells out, with a clear progress indicator + the exact command surfaced in the log
Missing-tool UX
Section titled “Missing-tool UX”Whenever Quay shells to a CLI binary, the missing-tool state must show:
- The exact command Quay tried to run
- A platform-aware install hint with copy + download buttons
(
brew install postgresql@16on macOS, the corresponding apt command on Linux, the Postgres installer link on Windows) - A clear “Continue with native fallback” button that doesn’t require the CLI
The user is never stuck because Quay can’t find a tool. Worst case, they pick the native path with one click.
Where this is enforced
Section titled “Where this is enforced”In code review. There’s no automated rule (yet) — but every PR that
introduces a Command::new("…") shell-out gets reviewed against
the question “does this feature work without that command?”. If
the answer is no, the PR doesn’t merge until the native path
exists.
Why this is the second rule, not the first
Section titled “Why this is the second rule, not the first”The North Star is confidence over breadth — the
first rule. Zero external deps follows from that: a feature that
sometimes works (when the CLI is installed in the right version on
the right path) doesn’t build confidence; it builds uncertainty.
A user can’t trust “backup works” if “works” depends on which pg_dump.