UUIDs show up everywhere — primary keys, idempotency keys, distributed tracing IDs, session tokens — because they solve a real problem: generating a unique identifier without coordinating with a central authority. But "UUID" isn't one thing. There are several versions with genuinely different properties, and picking the wrong one for the job is a common, mostly invisible mistake.
What a UUID Actually Is
A UUID (Universally Unique Identifier, also called a GUID on Windows/.NET) is a 128-bit value, conventionally written as 32 hex digits in five groups:
550e8400-e29b-41d4-a716-446655440000
The third group's first character encodes the UUID version (4 above means version 4), which tells you how the value was generated and what guarantees it actually carries.
UUID v1: Time and MAC Address Based
Version 1 UUIDs are built from the current timestamp and the generating machine's MAC address (or a random substitute if unavailable). This makes them sortable by creation time in a rough sense, which is genuinely useful for some indexing patterns — but it also means a v1 UUID leaks information about when and, historically, on what machine it was generated. That's a real privacy consideration if these ever end up in a public-facing context (a URL, an API response), which is one reason v1 has fallen out of favor for anything user-facing.
6ba7b810-9dad-11d1-80b4-00c04fd430c8
UUID v4: Fully Random
Version 4 is what most people mean when they say "just give me a UUID." It's 122 random bits (6 bits are fixed to mark the version and variant), generated with no reference to time, machine, or any external input:
f47ac10b-58cc-4372-a567-0e02b2c3d479
This randomness is exactly what makes v4 the right default for most application use cases — it carries no information leakage and doesn't require any coordination to generate safely, even across many machines generating IDs concurrently. Our UUID Generator produces v4 UUIDs using the browser's cryptographically secure random number generator (crypto.getRandomValues), which matters — a UUID generated with a weak or predictable random source loses its collision guarantees regardless of the version number in the string.
How Collision Probability Actually Works
The oft-repeated line is that UUID collisions are "essentially impossible," and for v4 specifically, the math backs that up: with 122 random bits, you'd need to generate roughly 2.7 quintillion UUIDs before the probability of a single collision reaches 50% (this is the birthday-paradox calculation, not a naive 1-in-2^122 estimate). For context, even generating a billion UUIDs a second, that threshold is billions of years away.
The important caveat: this guarantee assumes a correctly implemented, properly seeded random source. UUIDs generated from a weak PRNG, or from Math.random() in older JavaScript implementations without cryptographic guarantees, don't carry the same collision resistance the version number implies — the 122-bit math only holds if the bits are actually random.
When a UUID Is the Wrong Primary Key
UUIDs are popular as database primary keys because they can be generated client-side before an insert, avoiding a round trip to get an auto-increment value. But this comes with real costs that are easy to underestimate:
- Index fragmentation. Random UUID v4 values inserted as a primary key scatter across a B-tree index in random order, causing significantly more page splits than sequential integers — this is a measurable performance cost on large tables in MySQL/InnoDB and similar engines.
- Storage size. A UUID is 16 bytes (or 36 as a string); a
BIGINTis 8 bytes. On a large table with several secondary indexes referencing the primary key, this adds up. - No natural ordering. If you need "recently created" queries to be index-friendly, a random UUID gives you nothing — you need a separate
created_atindex anyway, which somewhat undercuts the "one column, no extra index" appeal.
A common middle ground worth knowing about: UUID v7 (finalized in RFC 9562), which embeds a millisecond timestamp in the leading bits while keeping the rest random. This gives you roughly sortable-by-creation-time IDs with v4-like collision resistance, and increasingly good database index locality — it's a genuinely better default for new primary-key designs than v1 or v4 if your database driver and libraries support it.
Summary
- v1 UUIDs encode timestamp and machine info — useful for rough time-ordering, but leak generation context, which matters for anything user-facing.
- v4 UUIDs are fully random and the right default for most application-level unique IDs — use our UUID Generator for a quick, browser-local one.
- Collision probability for v4 is astronomically low, but only if the underlying random source is cryptographically secure — verify your generator, don't just trust the version number.
- Random UUIDs make poor B-tree primary keys at scale due to index fragmentation; consider UUID v7 or a sequential ID if insert performance on a large table matters.