A full-stack Next.js app that connects to PostgreSQL, reads live metadata, and renders an animated lineage graph.
- Where data came from via dependency edges for:
- views
- materialized views
- Where data is going via downstream dependencies
- How big it is via:
pg_total_relation_size(...)pg_relation_size(...)- row estimates from
pg_class.reltuples
- How tables relate via foreign keys
PostgreSQL can reveal object dependencies (for views/materialized views) and foreign-key relationships directly from metadata.
It cannot fully reconstruct ETL lineage between ordinary tables unless that lineage is also represented in:
- views/materialized views
- dbt metadata
- orchestration metadata (Airflow, Dagster, etc.)
- query history / statement logs
This app auto-builds the best graph PostgreSQL can provide from live metadata alone.
npm install
cp .env.example .env.local
npm run devOpen http://localhost:3000.
See .env.example.
- Put the app near the database network-wise
- Use a read-only Postgres role
- Restrict schemas with
INCLUDE_SCHEMAS - Add dbt manifest ingestion later for full warehouse lineage
pg_classpg_namespacepg_total_relation_sizepg_relation_sizepg_dependpg_rewritepg_attributepg_constraint
- Dependencies: view/materialized-view/table dependencies
- Foreign keys: table relationship graph
- Combined: both
- Dependency edge means: "Object A reads from object B."
- Typical example: a view selects from a table.
- Foreign key edge means: "Rows in table A reference rows in table B."
- Typical example:
timeline.rule_idpoints toproduction_timeline_rules.id.
- Typical example:
The UI supports live pulses:
- node pulse for inserts/deletes (from
pg_stat_user_tablesdeltas) - edge traveling pulse for source -> target events (from an optional event table)
Create this optional event table:
create table if not exists public.lineage_activity_events (
id bigserial primary key,
created_at timestamptz not null default now(),
source_schema text,
source_table text,
target_schema text,
target_table text,
action text not null,
row_count integer not null default 1
);Example trigger log for production_timeline_rules -> timeline row creation:
insert into public.lineage_activity_events (
source_schema,
source_table,
target_schema,
target_table,
action,
row_count
)
values ('public', 'production_timeline_rules', 'public', 'timeline', 'insert', 1);When this row is written, the dashboard animates a pulse along the edge between those relations.
Ready-to-run trigger script for that flow:
sql/lineage_activity_timeline_triggers.sql
Apply it with:
psql "$DATABASE_URL" -f sql/lineage_activity_timeline_triggers.sqlAny standard Next.js deployment works. Vercel, self-hosted Docker, or a VM are all fine as long as the runtime can reach PostgreSQL.