foundation

Primary keys

Choose stable identifiers that support references, clustering, migration, and application-level identity.

A primary key uniquely identifies each row and is the anchor for foreign keys, ORM identity, and often the clustered index order. It must be unique, non-null, and stable for the row's lifetime.

| Strategy | Pros | Cons | |----------|------|------| | Surrogate (`BIGSERIAL`, UUID) | Stable, simple joins | UUIDs widen indexes; sequential IDs leak volume | | Natural (email, SKU) | Human-meaningful | Can change; composite keys complicate ORMs | | Composite (`(tenant_id, local_id)`) | Fits multi-tenant sharding | Wider FK columns; ORM friction |

					-- PostgreSQL: time-ordered UUID v7 or bigint identity
CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email TEXT NOT NULL UNIQUE
);
				

In InnoDB the primary key defines row clustering — random UUID inserts cause page splits; monotonic keys improve insert locality but expose ordering. Prefer `BIGINT` identity for high-volume OLTP unless you need global uniqueness without coordination.

On interviews: justify a key choice for a concrete table — why not email as PK, when UUID beats serial, and how migrations handle key changes.

Common pitfalls: no primary key (blocks replication tools, complicates ORM); mutable natural keys as PK; `INT` when tables will exceed 2B rows; random UUID PK on write-heavy InnoDB without measuring bloat.

The trade-off is balancing insert performance, global uniqueness, human readability, and migration safety — pick the key shape that matches how rows are created, referenced, and sharded.

Checklist:

  • State why the PK will not change for a row's life.
  • Compare surrogate vs natural for the domain.
  • Mention clustering / index locality impact.
  • Explain how child tables reference the PK.
  • Note sharding or multi-tenant implications.