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.
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/12tells 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:
- Use UUID v7 (sortable).
- Use a hybrid: store the UUID as an additional column, use a serial integer as the actual PK.
- 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.