Skip to content
Guides

How UUIDs work, and when to use which version

UUID v4 vs v7 vs ULID — when to use each, and why "random globally-unique ID" is more subtle than it looks.

May 26, 20264 min read
UNIQUE IDSUUIDGUIDEf47ac10b-58cc-4372-a567-0e02b2c3d479v4 · Randomv7 · Time-sortable128-bit · 36 characters · collision-safe

A UUID is a 128-bit identifier you can generate anywhere, no coordination required, with negligible chance of collision. They're the bones of every modern distributed system — and the UUID Generator gives you as many as you want, on demand.

What "globally unique" really means

A UUID v4 is 128 random bits. Of those, 122 are random and 6 are fixed (the version and variant). That gives 2^122 possible values — roughly 5 × 10^36.

To get a 50% chance of a collision (the birthday paradox), you'd need to generate about 2.7 × 10^18 UUIDs. If a team generated a million UUIDs every second, that would take 85,000 years.

So: yes, you can use UUIDs as IDs without a central registry and never collide. The math holds.

v4 vs v7 vs ULID

UUID v4: purely random. The default and most common. Looks like f47ac10b-58cc-4372-a567-0e02b2c3d479. Excellent for primary keys, idempotency tokens, request IDs.

UUID v7 (released 2024): time-ordered. The first 48 bits encode the timestamp (milliseconds since epoch). The rest is random. Looks like 01890af2-.... Sorts chronologically by default, which is a huge benefit for database indexes — inserts go at the end of the B-tree instead of randomly into the middle.

ULID: Universally Unique Lexicographically Sortable Identifier. Similar concept to UUID v7 but encoded in Crockford Base32, so it's only 26 characters instead of 36 and is case-insensitive. Looks like 01ARZ3NDEKTSV4RRFFQ69G5FAV.

For new databases in 2026, v7 is the right default. It gets you UUID compatibility (you can still store it as UUID in PostgreSQL) plus the index-friendliness of a sortable ID. The tool here generates v4 by default; we may add v7 later.

When to use a UUID (vs an auto-increment integer)

Use UUIDs when:

  • You're sharding or partitioning. Auto-increment doesn't work across shards.
  • You're generating IDs on the client (mobile app, offline-first web app). Avoids round-trip to the server.
  • You need URLs that don't leak count information. /orders/12 tells competitors how many orders you have. /orders/f47ac10b-... doesn't.
  • You're building event streams or message queues that need at-least-once delivery deduplication.

Stick with auto-increment when:

  • You have a single database with no sharding plans.
  • Storage cost matters and you have billions of rows. A 4-byte int beats a 16-byte UUID 4 to 1.
  • The IDs will be typed by humans (support tickets, order numbers). "Order #12345" beats "Order f47ac10b-..."

Performance notes

UUIDs as primary keys in random insertion order can fragment B-tree indexes badly. PostgreSQL's gen_random_uuid() produces v4, which has this problem. The fix is one of:

  1. Use UUID v7 (sortable).
  2. Use a hybrid: store the UUID as an additional column, use a serial integer as the actual PK.
  3. Just live with the fragmentation. Modern SSDs make it less catastrophic than it used to be.

For tokens, idempotency keys, and short-lived IDs (where you don't care about index order), v4 is perfect — and that's what the generator produces. Click, copy, ship.

Tags#uuid#id#database#how-to

More from Guides

See all →