Software & TechnicalFree
Document a Database Schema's Columns
Paste your schema and get a column register grouped by business domain, with each column's meaning and any name that no longer matches its data.
River's schema tool takes the dump and writes what the dump cannot say. Every table sorted into the business domain it belongs to rather than the alphabet. Every column carrying its inferred purpose, its declared nullability beside what the data actually holds, its indexes and its real relationships. Then the entity diagram redrawn one domain at a time, because a single diagram of eighty tables is a picture of eighty tables and teaches nobody anything.
Page one splits between diagram tools and best-practice checklists. The diagram tools are good and they answer a question nobody was stuck on, which is what the tables are called and how they join. The checklists say to keep documentation current, define naming conventions and add descriptions. Both stop exactly where the difficulty starts: the column called status with eleven values, four of which stopped occurring in 2021, and nothing anywhere saying what any of them meant.
Built for the analyst joining a company with a decade-old warehouse, the engineer whose first ticket touches a table they have never seen, and the team about to migrate a schema nobody can fully explain. Reach for it before you write the first query. Where the schema belongs to a service you also inherited, the inherited codebase documentation reads the code that writes to it, and a column whose shape came from a decision worth keeping belongs in an architecture decision record. The API documentation pack covers the same tables seen from outside.
The database has a documentation slot and it is empty
PostgreSQL ships the place this documentation belongs. A single COMMENT ON COLUMN statement attaches a sentence to a column, the text comes back through col_description, it appears in psql's table listing, and it travels with the schema into every dump and every replica. Almost nobody fills it in. A register that emits those statements beside the document puts the meaning where the next person is already looking, which is the only reason documentation ever stays current.
A dropped column is hidden, not deleted. PostgreSQL states that the DROP COLUMN form does not physically remove the column but simply makes it invisible to SQL operations, and that the space is reclaimed only as existing rows are updated. So a schema document claiming a field was removed in 2023 is describing what SQL can see. For a retention question, a privacy review or a subject access request, that distinction is the entire answer.
The dump is often incomplete, and it never says so. PostgreSQL documents that in the columns view of the information schema, only those columns are shown that the current user has access to. Run the extract as a reporting role rather than the owner and tables vanish silently, which reads exactly like a schema that does not have them. So the register opens with a completeness check: the table count, the column count, and the role the extract ran as.
How it works
Paste the schema
A schema-only dump, a create script, an ERD export or the catalogue query output.
Say what it does
One paragraph on the business, which is what turns eighty table names into seven domains.
River builds the register
Purpose per column, declared against observed, relationships traced, and the names that no longer fit.
Push it back
Take the document, the per-domain diagrams and the comment statements that put meaning in the database.
What you get
- Every table sorted into a business domain, with the tables that fit nowhere named
- A column register carrying inferred purpose, declared nullability and what the data actually holds
- The columns whose names no longer describe their contents, each with the evidence
- COMMENT ON COLUMN statements so the register lives inside the database, not a wiki
- Relationships the foreign keys declare and the ones only the application enforces
- An entity diagram per domain rather than one unreadable picture of every table
Common questions
I only have a schema dump, no data. How much can you tell me?
Structure, completely: tables, columns, types, keys, indexes, defaults and constraints. Purpose, mostly, because a name plus a type plus a foreign key plus a default is a strong signal and eighty tables together are stronger. What needs the data is the gap between declared and actual, so those rows arrive marked as unverified with the one query that would check each.
How does it know a column name no longer matches its contents?
From disagreement between sources. A type that is wider than every value in it, a boolean carrying three states through NULL, a name saying cents where the values are clearly dollars, a foreign key column pointing at two tables depending on a sibling column. Each finding names both the name and the evidence against it.
We use dbt, and our models already have descriptions.
Then you have descriptions for the models and nothing for the source tables underneath, which is where the ambiguity lives. This documents the physical schema, and the two fit together: the register explains what a raw column holds, and your model descriptions explain what you turned it into. The data pipeline documentation pack covers the transformation layer.
Which database does it work with?
Any dump you can paste. Postgres, MySQL, SQL Server, Oracle, Snowflake, BigQuery, SQLite. The structural questions are the same everywhere and the syntax differences are only syntax. Where a flavour has behaviour worth knowing, such as how it treats an empty string against NULL, the register says so on the rows it affects.
Can it draw the diagram?
One per domain, which is the only version anyone reads. A single picture of eighty tables gets printed, admired and never opened again. Seven pictures of eight to fifteen tables each get used, because a person working on billing can see billing without tracing a line across a wall. The join keys are labelled on every relationship.
What about the tables nobody can place in a domain?
They get their own section, and it is worth reading first. A table that fits no domain is usually one of three things: a staging table somebody forgot, a feature that was built and abandoned, or a domain the business has and nobody mentioned. Each one arrives with its row count, its last write and the check that would settle it.
We are about to migrate this schema. Does that change anything?
It raises the stakes on two sections. The relationships the application enforces without a foreign key are the ones a migration breaks silently, and they are invisible in the dump. The columns whose names no longer match get mapped wrong in the new model. Both are called out for that reason. A migration that changes a caller-visible field belongs in the release notes as well.
Document a Database Schema's Columns
Fill in the form and your workspace opens with the work already underway.