Table created without a primary key
Note — this works and blocks nothing, but a performance regression is likely.
What it catches
A table without a primary key (or any unique constraint) works until it doesn't: logical replication rejects UPDATE/DELETE without a replica identity, targeted row operations degrade to full scans, and maintenance tooling that addresses rows by key can't help you. Adding a key later on a populated table is exactly the migration this tool exists to warn about.
Fires on
CREATE TABLE audit_log (entry text, created_at timestamptz);Do this instead
Give every table a primary key at creation, when it costs nothing — a bigint identity column is the default answer. It provides the replica identity logical replication requires, and spares you the ADD PRIMARY KEY migration on a populated table later.
CREATE TABLE audit_log (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
entry text,
created_at timestamptz NOT NULL DEFAULT now()
); This rule runs in the hosted service on Startup and above — add --remote with a team token, or use the GitHub Action: npx bolvrk check migration.sql