How Querybara works
The Querybara desktop app is an Electron app split into several processes, each with one job. The page you work in has no Node.js and no database drivers. Each open connection gets a process of its own, long jobs run in another, and the main process keeps the local store, the secrets and the scheduler. This page explains who does what and how data moves between them.
- The window is a React page without Node.js. Its preload is sandboxed and only forwards message ports.
- The page talks to the main process over a MessagePort: typed calls, each message validated with zod.
- Opening a connection starts a utility process for it, and main hands the page a port straight to that host.
- Passwords and keys go from main to the hosts only. The page never holds them.
- Result rows go from the host straight to the page, never through main.
- Imports, exports, compares and backups run in a job runner process started on demand; main relays their progress.
The processes
Section titled “The processes”| Process | What it does |
|---|---|
| Main | App lifecycle, the window, the local store, the main RPC contract, the scheduler, and supervision |
| Preload | Sandboxed. Hands RPC ports to the page and exposes nothing else but platform and version strings |
| Renderer | The React interface. A sandboxed web page without Node.js |
| Connection host | One utility process per open connection. Loads the driver, opens the sessions and any SSH tunnel |
| Job runner | One utility process, started on demand, for jobs: imports, exports, backups, transfers, compares and more |
Database drivers never load into main or the renderer. They run only in connection hosts and the job runner.
Main opens the local store, answers the page’s requests on the main contract (profiles, settings, history, jobs, schedules, updates), starts connection hosts and the job runner, and checks SSH host keys for both. It also holds the secrets: saved passwords are unsealed here and nowhere else in the app. The scheduler and the desktop notifications run here too.
On Windows and Linux the page draws the window’s title bar and its menu bar; each menu item runs in main, as the native menu’s would.
Preload and renderer
Section titled “Preload and renderer”The renderer is served from Querybara’s own app://querybara/ origin, with a Content Security Policy
that allows nothing remote. It runs sandboxed, without Node.js, with context isolation.
The preload is a dozen lines with no logic of its own. It forwards message ports from main to the
page after checking their shape, and the page accepts a port only from its own window and origin.
No ipcRenderer method is reachable from the page.
Connection hosts
Section titled “Connection hosts”Opening a connection starts a utility process for it. The host receives the resolved profile from main, loads the driver, opens the SSH tunnel or proxy route when the profile has one, and serves the connection’s RPC contract directly to the page. Every tab of a connection uses the same host, and the tunnel’s SSH session is shared between them.
A crashed host closes its ports, so the page learns about it at once, and main reports the restart or failure. The page reconnects by asking main for the connection again, which hands it a new port.
Job runner
Section titled “Job runner”Long work runs in one job runner process: imports, exports, Run SQL File, data transfers, backups and restores, structure and data compares and their applies. It also answers requests that belong to no job: the wizards’ previews and column matching, and the reading of a Redis dump file for Dump analysis. Main starts it when the first job or request arrives and stops it after 30 seconds with nothing running.
Jobs run side by side, each with its own driver session and, for a profile with SSH or a proxy, its own tunnel. A job survives closing its tab. If the runner exits, the jobs it was running fail and the next job starts a new runner. Cancel aborts the job at the next batch, and an import rolls back its transaction.
The page never talks to the runner directly. Main relays progress, logs and results, since job traffic is progress, not result rows.
How messages travel
Section titled “How messages travel”Every RPC channel is a MessagePort. Main creates a channel, serves its end, and transfers the
other end to the page through the preload. The RPC is typed (@querybara/ipc), and every message is
validated with zod on arrival. Streams, progress events and cancellation work the same way on
every channel.
| Channel | Carries |
|---|---|
| Page ↔ main | The main contract: profiles, settings, history, jobs, schedules, updates |
| Page ↔ connection host | Queries, result rows, browsing, edits for that connection |
| Main ↔ connection host | Control: connect, check, attach, shutdown; ready, failed, host keys |
| Main ↔ job runner | Control: start, cancel, requests; progress, logs, done, host keys |
The control channels between main and the hosts or the runner never carry anything towards the page.
Secrets
Section titled “Secrets”Secrets travel only from main to a connection host or the job runner, inside the resolved profile that opens a session. They never go to the page. The local store keeps saved passwords sealed by the OS keychain; see Security model.
The life of a query
Section titled “The life of a query”- You run all of the editor, the statement at the cursor, or the selection.
- The splitter cuts the text into statements. It understands DELIMITER, dollar quoting and nested comments, so a function body stays whole.
- Each statement passes the safety check: a risky write, or any write on a production profile, waits for you to confirm it.
- The statement goes to the connection’s own host process, then through the profile’s SSH tunnel if it has one, to the server.
- Rows stream from the host straight to the page, 1,000 at a time, into the results grid. They never pass through the main process.
- Cancel asks the server itself to stop the statement, and the session stays usable.
- You run all, the statement at the cursor or the selection. The page’s statement splitter cuts
the script into statements, respecting
DELIMITER, dollar quoting and comments. - The safety check decides whether a statement needs a confirmation, for example a risky write on a production profile, and the page asks you before it runs.
- The statement goes to the connection’s host over the connection’s port.
- The host runs it on its session, through the SSH tunnel when the profile has one.
- Rows stream from the host straight to the page, 1,000 at a time, into the result grid. They never pass through main.
- Cancel sends a server-side cancel for the running statement.
Comparisons and applies
Section titled “Comparisons and applies”Structure and data compares run as jobs in the runner, which opens both connections. Main keeps each finished comparison, and the page asks main for the script of the operations you selected.
An apply runs only the script you reviewed: the page sends its SHA-256, and the runner generates the script again from the kept comparison and refuses to run a different one. The write rules are checked twice, in main before the job starts and in the runner before each statement.
Data compares write their row differences to a folder under the system’s temporary folder, so a large difference never sits in memory.
Schedules
Section titled “Schedules”The scheduler lives in main and runs schedules only while Querybara is open. Nothing is installed in the operating system.
- It keeps each enabled schedule’s next run time, and wakes at the soonest one and at least once a minute. It also wakes when the computer resumes from sleep or the screen is unlocked, so a sleep or a clock change is noticed at once.
- Backups, SQL files and exports run as jobs in the job runner, after the same checks as a job you start yourself: the connection’s write rules, and the files and folders you picked. A saved comparison runs in the job runner as the Compare button runs it.
- A scheduled run cannot ask for a password. Each password the connection needs must be saved, or typed earlier in the session; otherwise the run fails and says so. The passphrase of an encrypted backup schedule is kept in the secret store, sealed like a saved password.
- A run more than two minutes late was missed, for example because Querybara was closed or the computer was asleep. Each schedule says whether a missed run is caught up once or skipped. A schedule that is still running when it is due again skips that run.
- Every run is recorded in the schedule’s history, skipped ones included. Main sends a desktop notification when a run fails or a comparison finds differences, or as the schedule says.
Closing Querybara with schedules on asks first, on every platform; there is no tray icon. The question is not asked when no schedule is on, when the system shuts down, restarts or logs out, or when Querybara restarts to install an update. On macOS, closing the last window leaves Querybara running, so only quitting asks.
The CLI
Section titled “The CLI”The shared packages never import Electron. querybara, the command-line tool, runs the same drivers,
sync engine, transfer and backup code in a single Node.js process, and opens its own tunnels. See
the CLI reference.
Related
Section titled “Related”Documents Querybara 0.1.1 · built frombc9f5aa