UUIDs as first-class identifiers
PostgreSQL has built-in UUID type and built-in generators: gen_random_uuid() (v4) and uuidv7() (PG 18+). Pre-PG 18 you'd add the uuid-ossp extension; PG 13+ has gen_random_uuid in the core.
v4 vs v7
v4: 122 random bits. Globally unique, but completely unsorted — every insert into a B-tree index lands at a random position, fragmenting the index over time. Fine for IDs you read by exact lookup; not great for primary keys.
v7: 48-bit timestamp + 74 random bits. Globally unique AND time-sortable. New rows land at the end of the index (just like a sequential integer), and ORDER BY the UUID gives chronological order for free.
When to use which
Internal primary keys: integer IDENTITY (cheap to join, smaller indexes). Public-facing IDs you expose in URLs/APIs: uuidv7() if available, else gen_random_uuid(). Many tables have both — internal id for joins, external uuid for exposure.