Skip to main content
Aarunya AppsAarunya Apps
๐Ÿ› ๏ธ Developer8 min readยทSeptember 16, 2026

UUID v4 vs v7 vs ULID: Which Should You Use as a Primary Key?

Choosing a primary key format is a decision you live with for the lifetime of your database. UUID v4 is ubiquitous but unsortable. UUID v7 solves that. ULID is a newer alternative. Here's what each one means for your database performance.

UUID v4 โ€” fully random

550e8400-e29b-41d4-a716-446655440000

UUID v4 is 128 bits of randomness (except 6 bits for version/variant). It's the default everywhere โ€” every language has a uuid() function that generates v4. The problem: random IDs cause B-tree index fragmentation. New rows insert at random positions in the index, causing page splits and poor cache locality. At scale, this measurably increases write latency.

UUID v7 โ€” time-ordered (RFC 9562)

019260a3-c6c0-7000-8d4e-f2d4a1c3b5e7
# first 48 bits = Unix timestamp in milliseconds

UUID v7 is sortable by creation time. The first 48 bits are a millisecond-precision Unix timestamp, followed by a version field and random data. This means new rows insert at the end of the index โ€” the same access pattern as auto-increment integers. Index fragmentation is eliminated.

UUID v7 is ideal for:

  • PostgreSQL with uuid column type
  • Any system that needs globally unique IDs without a central coordinator
  • Microservices generating IDs independently (no coordination needed)

ULID โ€” Stripe-style, URL-safe

01ARZ3NDEKTSV4RRFFQ69G5FAV
# 26 chars, Crockford Base32, first 10 chars = timestamp

ULID (Universally Unique Lexicographically Sortable Identifier) is also time-ordered. It uses Crockford Base32 encoding โ€” only uppercase letters and digits, no ambiguous characters (0/O, 1/I). This makes it URL-safe and human-readable. Stripe customer IDs (cus_xyz) follow a similar pattern.

Side-by-side comparison

PropertyUUID v4UUID v7ULID
SortableโŒ Randomโœ… ms precisionโœ… ms precision
Index-friendlyโš ๏ธ Fragmentationโœ… Sequentialโœ… Sequential
URL-safeโš ๏ธ Contains -โš ๏ธ Contains -โœ… Base32
Length36 chars36 chars26 chars
Bit collision riskVery lowVery lowVery low
Language supportEverywhereGrowing (2023+)Good (libraries)
DB native typeuuid / binary(16)uuid / binary(16)varchar(26)

Recommendation

  • โ†’New system, PostgreSQL โ†’ use UUID v7. It's an RFC standard (RFC 9562, 2024), sortable, and compatible with any uuid column.
  • โ†’New system, prefer short readable IDs โ†’ use ULID. Great for customer-facing IDs in URLs.
  • โ†’Existing system already using v4 โ†’ keep v4. Migration cost rarely outweighs the benefit unless you're experiencing index fragmentation at scale.
  • โ†’Need compatibility with auto-increment ordering โ†’ UUID v7 or ULID. Both sort chronologically.

Generate UUID v4, v7, ULID, and more in bulk with the UUID / ULID Generator โ€” includes a bit-level breakdown of each format so you can see exactly what each section encodes.

Try the related tool

UUID / ULID Generator โ€” free, runs 100% in your browser.

Open UUID / ULID Generator โ†’

Enjoyed this? Get notified when Pro launches.