A free online EXPLAIN plan visualizer. Paste the EXPLAIN output of a PostgreSQL, MySQL/MariaDB, SQLite, SQL Server or Oracle query and explore it as an interactive graph, diagram, table and statistics view, with automatic performance findings.
Try it online · Use it in Tabularis · npm package · Discord
- Four views: an interactive graph, a compact diagram, a sortable table and summary statistics.
- Automatic findings: hotspots, bad row estimates, disk sorts, large sequential scans and cache misses are flagged on each node.
- Encrypted sharing links: the plan is encrypted in the browser before it is stored, and the key exists only in the link, so the server cannot read it. Links expire 30 days after they were last opened.
- Auto-detection: the engine and format are detected from the pasted text, or you can pick them by hand.
Note
Plans are parsed in your browser and no query is ever executed. Nothing is sent anywhere until you click Share, and a shared plan is encrypted before it leaves your browser.
Built on @tabularis/explain, the engine behind the Visual EXPLAIN feature of Tabularis, the open-source database client.
| Engine | Formats |
|---|---|
| PostgreSQL | EXPLAIN (FORMAT JSON), plain EXPLAIN / EXPLAIN ANALYZE text |
| MySQL / MariaDB | EXPLAIN FORMAT=JSON, EXPLAIN ANALYZE / ANALYZE FORMAT=TEXT trees |
| SQLite | EXPLAIN QUERY PLAN: the sqlite3 shell tree (|-- / `--) or raw id|parent|…|detail rows |
| SQL Server | SHOWPLAN_XML estimated plans and STATISTICS XML actual plans (ShowPlanXML documents) |
| Oracle | oracle-plan-json: PLAN_TABLE rows as JSON (see below), or the payload captured by the Tabularis Oracle plugin |
The app shows the command to run for each engine under the editor.
Oracle has no JSON EXPLAIN output, so the app reads the PLAN_TABLE rows as a JSON document. Run this in SQLPlus, SQLcl or SQL Developer (Oracle 12.2+) and paste the returned value. In SQLPlus, run SET LONG 1000000 first so the result is not truncated. The query lives in oracle-query.ts.
EXPLAIN PLAN FOR SELECT …;
SELECT JSON_OBJECT(
'version' VALUE 1,
'statistics' VALUE 'false' FORMAT JSON,
'plan' VALUE JSON_ARRAYAGG(JSON_OBJECT(
'id' VALUE id, 'parent_id' VALUE parent_id, 'depth' VALUE depth,
'position' VALUE position, 'operation' VALUE operation,
'options' VALUE options, 'object_owner' VALUE object_owner,
'object_name' VALUE object_name, 'object_alias' VALUE object_alias,
'object_type' VALUE object_type, 'optimizer' VALUE optimizer,
'cost' VALUE cost, 'cardinality' VALUE cardinality, 'bytes' VALUE bytes,
'cpu_cost' VALUE cpu_cost, 'io_cost' VALUE io_cost, 'time' VALUE time,
'access_predicates' VALUE access_predicates,
'filter_predicates' VALUE filter_predicates,
'projection' VALUE projection, 'qblock_name' VALUE qblock_name
NULL ON NULL RETURNING CLOB)
ORDER BY id RETURNING CLOB)
RETURNING CLOB)
FROM plan_table
WHERE plan_id = (SELECT MAX(plan_id) FROM plan_table);- Vite + React 19 + TypeScript
- React Router for the home and plan pages
- Tailwind CSS 4 and CSS Modules, with the Tabularis design tokens
@tabularis/explainfor parsing, analysis and the plan views@tabularis/explain-sqlserverfor SQL Server SHOWPLAN XML@tabularis/explain-oraclefor Oracle execution plans- Cloudflare Workers and R2 for the sharing links
- Vitest + Testing Library for tests
pnpm install
pnpm dev # local dev server
pnpm test # run the test suite
pnpm test:coverage # run the tests with a coverage report in coverage/
pnpm typecheck # TypeScript only
pnpm build # typecheck + production build into dist/
pnpm preview # serve the production build locallyAll SEO is driven by seo.config.json: title, description, keywords, canonical URL, Open Graph and Twitter cards, robots, theme color and JSON-LD. The tags are injected into index.html at build time by the seo-inject plugin in vite.config.ts, so customizing the SEO never requires touching the HTML or the app code.
seo.config.json → image points at public/og.png, the 1200×630 social card.
The site is a fully static single-page build:
vercel deploy(Framework preset: Vite, build command pnpm build, output directory dist.)
Sharing links are served by a small Cloudflare Worker in worker/, deployed at share.tabularis.dev. The browser compresses and encrypts the plan with AES-GCM, sends only the ciphertext, and keeps the key in the part of the link after #, which browsers never send to a server. The Worker stores the ciphertext in an R2 bucket, where a lifecycle rule deletes it 30 days after its last write. Opening a link rewrites a blob that is more than a day old, so links expire 30 days after they were last opened.
cd worker
pnpm wrangler deployIn development, Vite proxies /api to the deployed Worker, so pnpm dev works without running it locally.
Tip
Join our Discord server to talk with the maintainers, share feedback, and get help from the community.
Released under the Apache License 2.0.

