Skip to main content

Postgres · Supabase · read-only

SELECT structure FROM your undocumented database;

DataLineageTracer reads the catalog a Postgres database keeps about itself — pg_catalog, and pg_stat_statements where it is installed — and draws what is actually there: every table and view, every foreign key as a crow’s-foot edge, the key-shaped columns no constraint covers, and the statements costing the most time.

Used in memory for one trace, then discarded — never written to disk or to a database. Supabase credentials and read-only setup or open the example trace.

What happens when you press trace

  1. 01

    The connection string is parsed and the host is vetted

    Only postgres:// and postgresql:// are accepted. The hostname is resolved and every address it answers with is checked; loopback, private, link-local and reserved ranges are refused, and the connection is then made to the address that passed rather than to a second lookup.

  2. 02

    One read-only session reads the catalog

    Every statement the trace runs is a SELECT against a system catalog — pg_class, pg_attribute, pg_constraint — and the session asks Postgres to refuse writes on top of that. Nothing in your tables is read: only the catalog's description of their shape, the row estimates the planner already keeps, and, where pg_stat_statements is readable, the normalised statement text it records.

  3. 03

    The connection closes and the credentials go with it

    The connection string exists in server memory for the length of that one request. It is never written to a disk, a log line or a database, and there is nothing to re-sync from later.

  4. 04

    The snapshot is drawn and kept in your browser

    Tables are laid out by how far downstream they sit, joined by crow's-foot edges. Selecting one pulses its lineage in both directions. The snapshot is stored in this browser's localStorage — there is no account and no server-side copy.

What the map shows you that a schema dump does not

A dump tells you what exists. The map tells you what is joined to what, which is the question you actually have when you inherit a database. Selecting orders lights the path back through customers and forward into order_items, payments and shipments, with the direction of the pulse showing which way the keys point.

Two flags sit on top of that. Columns named like references that no foreign key covers are the joins someone made in application code and never told the database about. Statements from pg_stat_statements are matched back to the relations they name, so an expensive query marks the tables it lands on.

PK
Column is part of the primary key.
FK
Column is covered by a foreign-key constraint.
?
Column is named like a reference — an _id, _key or _fk suffix — but no constraint covers it. A naming heuristic, not proof.
HIGH COST
A statement naming this relation averages over 100 ms, or takes a tenth of all recorded time.

What this version does not do

  • Postgres only. MySQL, SQL Server and the rest are not supported, and there is no adapter behind the form pretending otherwise.
  • Point-in-time snapshots. A trace is manual. There is no monitoring, no re-sync and no drift history, because keeping any of those would mean storing your credentials.
  • No accounts, no server-side storage. Traces live in the browser you ran them in. Clearing site data removes them, and they do not follow you to another machine.
  • Read-only, always. Nothing here writes, migrates or edits a schema — every statement it sends is a SELECT against a system catalog.
  • Query cost depends on your server. Without pg_stat_statements installed and readable, a trace still maps the schema — it just has no timings to show, and says so rather than filling the gap.