Every table has an explicit primary key
Why it matters
Tables without explicit primary keys are unpredictable to query, replicate, and join. Without a declared PK, Postgres cannot enforce entity uniqueness at the database level, ORMs like Prisma refuse to generate correct update and delete operations, and replication tools (Supabase logical replication, AWS DMS) silently skip or mis-replicate affected rows. Junction tables without composite PKs allow duplicate relationship rows that violate relational integrity. The ISO 25010 functional-correctness requirement is unambiguous: every entity must have a stable, unique identifier declared in the schema — not inferred from an implicit rowid that disappears the moment you add a real column.
Severity rationale
Critical because missing PKs break ORM operations, block correct replication, and allow duplicate rows in junction tables — all three failures can corrupt application state silently.
Remediation
Add an explicit @id (Prisma) or PRIMARY KEY (SQL) declaration to every table that lacks one. For entity tables, use a UUID or serial surrogate. For junction tables, use a composite PK over both FK columns.
model PostTag {
postId String
tagId String
@@id([postId, tagId])
}
CREATE TABLE audit_logs (
id BIGSERIAL PRIMARY KEY,
user_id UUID NOT NULL,
action TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
After adding PKs to existing tables, run VACUUM ANALYZE to refresh planner statistics.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Database Design & Operations Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- iso-25010:2011 · functional-suitability.functional-correctness — Functional Correctness
Taxons
History
- 2026-04-18·v1.0.0·Initial import from database-design-operations·automated