ideas.
September 09, 2026 3 min read desktopdev-toolsdata

A SQL client that can't nuke production

A desktop database console that estimates blast radius, forces transactions on prod, and logs every statement you run against live data.

The idea

A desktop SQL client that treats every connection as having a risk level. Point it at your local database and it behaves like any other client. Point it at production and it changes: destructive statements get an estimated row count before they run, every write opens inside an explicit transaction you have to commit yourself, and each statement is appended to a local audit log with the reason you typed when you opened the connection. Same editor, same autocomplete, different rules depending on where you're pointed.

Why build this

The standard database GUIs are environment-blind. The connection dropdown is a colored dot, and the difference between staging and production is one careless click. Everyone who has run a database console for a few years has a story — the UPDATE with the WHERE clause still highlighted, the DELETE fired against the wrong tab after lunch. Teams paper over this with policy ("never query prod directly") that nobody follows, because sometimes you genuinely need to inspect live data during an incident.

The tooling gap is real: the safety features exist in bits and pieces (dry-run flags, read-only replicas, bastion audit logs) but none of them live where the risk actually is, which is the text box where someone types a statement at 2am. A client that puts the guardrail in the editor is a small product with a very clear pitch.

Stack sketch

  • Shell: Tauri v2 — Rust backend, web frontend, small binary, no bundled Chromium the way Electron does it.
  • Editor: Monaco with a SQL language service; libpg_query (via the pg_query.rs bindings) to parse statements properly instead of regexing for DELETE.
  • Drivers: sqlx for Postgres and MySQL, rusqlite for SQLite. Start with Postgres only.
  • Blast radius: rewrite the parsed statement into an equivalent SELECT count(*) over the same FROM/WHERE, run it in a read-only transaction, show the number. Fall back to EXPLAIN row estimates when the rewrite isn't safe.
  • Credentials: the keyring crate — OS keychain, never a plaintext JSON config next to the app.
  • Audit log: append-only JSONL in the app data directory, one line per executed statement with connection label, timestamp, statement text, and rows affected.

Scope for v1

In:

  • Postgres connections with a per-connection risk level (local, staging, production), set at creation and shown as a persistent banner.
  • Statement parsing that classifies each statement as read, write, or schema change.
  • Row-count preview and a confirmation dialog for any write or schema change on a production connection.
  • Autocommit disabled on production connections — an explicit Commit/Rollback bar appears after every write.
  • Local JSONL audit log with an in-app viewer.

Out: query history sync, team features, schema diagramming, saved-query sharing, MySQL, anything cloud. The whole point of v1 is that it stores nothing off the machine.

Where it could go

The natural second step is turning the audit log into something a team can use. A small self-hosted collector that receives statement records from each developer's client gives you a real answer to "who touched the orders table last Tuesday" — which today usually means grepping bastion host shell history. That's the feature that makes it a paid team product rather than a free utility.

Past that, the risk classifier is reusable. The same parser that decides whether to show a confirmation can run in CI against migration files, flagging a migration that drops a column or rewrites a large table without a lock timeout. Selling one engine as both a desktop guardrail and a pipeline check is a cleaner story than either alone.

Watch out for

The count-rewrite is the hard part: subqueries, CTEs, and UPDATE ... FROM can all make the naive rewrite return a number that doesn't match what the statement will touch. Be conservative — when the rewrite isn't provably equivalent, say "estimate unavailable" rather than showing a confident wrong number, because a trusted-and-wrong preview is worse than no preview at all.