developer · · Updated
Understanding UUIDs — What They Are and Why Developers Use Them
By Chirag
A UUID (Universally Unique Identifier) is a 128-bit value used to identify something — a database row, a session, a request — without needing a central authority to hand out the next available number.
What a UUID looks like
In text, a UUID is written as 32 hexadecimal characters split into five groups by hyphens, like 550e8400-e29b-41d4-a716-446655440000. The hyphens don't carry meaning beyond readability — the underlying value is just 128 bits.
Why "universally unique" isn't an exaggeration
A version 4 (random) UUID has 122 random bits, giving roughly 5.3 x 10^36 possible values. The birthday bound puts numbers on it: a table holding a trillion (10^12) random v4 UUIDs has about a 1 in 10^13 chance of containing even one duplicate, and a 50% chance needs around 2.7 x 10^18 of them. That is why most systems treat a collision as effectively impossible and put a unique index on the column to catch the case that matters in practice: a bug that reuses an ID.
Common UUID versions
Version 4 (random)
The version that crypto.randomUUID() in browsers and Node.js, Java's UUID.randomUUID() and PostgreSQL's gen_random_uuid() all produce: 122 random bits (the other 6 mark the version and variant), with no relationship to time, machine or input data.
Version 1 (timestamp-based)
Derived from the current timestamp and the generating machine's network address. It's sortable by creation time, but it can leak information about when and where it was generated, which makes it a poor choice when the ID itself shouldn't reveal metadata.
Version 5 (name-based)
Generated deterministically from a namespace and a name using a hash function — the same input always produces the same UUID. Useful when you need a stable, unique ID derived from existing data, like a URL or an email address.
Where UUIDs show up in practice
- Primary keys in distributed databases — systems like PostgreSQL and DynamoDB commonly use UUIDs as primary keys when rows might be created on multiple nodes or services without a shared counter.
- Idempotency keys — APIs for payments and order processing often ask clients to generate a UUID per request, so a retried network call can be recognized as a duplicate instead of creating a second charge or order.
- Object storage keys — file uploads to S3-style buckets are often given a UUID-based key to guarantee two users' uploads never overwrite each other, even with identical original filenames.
- Request and trace IDs — in a microservices architecture, a UUID generated at the edge and passed through every downstream service makes it possible to find every log line related to a single request.
Why not just use auto-incrementing IDs?
Auto-incrementing integers (1, 2, 3...) are simple and compact, but they come with tradeoffs UUIDs solve:
- No central coordination needed — a UUID can be generated on the client, in a distributed system, or offline, without asking a database for "the next number." Auto-increment requires a single source of truth.
- Harder to guess — sequential IDs make it trivial to enumerate records (e.g., /orders/1001, /orders/1002...). Random UUIDs remove that as an attack surface.
- Safe to merge across databases — if you ever need to merge records from two systems, auto-incrementing IDs are guaranteed to collide. UUIDs almost never will.
When auto-increment is still the better choice
UUIDs aren't free — they're larger (16 bytes vs 4 or 8 for an integer), which can matter for index size and join performance at scale, and their randomness (in v4) can hurt insert performance on certain database index structures. For a small internal table where IDs are never exposed or merged across systems, a simple auto-incrementing integer is often simpler and faster.
Version 7: random, but sortable by time
RFC 9562, published in 2024, added UUID version 7. It starts with a 48-bit Unix timestamp in milliseconds and fills the remaining bits with random data. Two v7 UUIDs created a second apart sort in creation order, while still being practically impossible to guess or collide. That fixes the main database drawback of v4: random v4 keys land at random positions in a B-tree index, so inserts touch pages all over it, while v7 keys arrive roughly in order like an auto-increment. PostgreSQL 18 added a built-in uuidv7() function, and libraries in most languages generate them. The trade-off is that a v7 ID reveals when it was created, so don't use it where the creation time itself is sensitive.
Generating v4 UUIDs for tests and fixtures
The UUID Generator creates random v4 UUIDs with the browser's built-in crypto.randomUUID(), one at a time or up to 50 at once — useful for seeding test data, mocking API responses, or generating unique keys during development.
Related guides
- HTTP Status Codes You Will Actually See, From One Real Site · Every status code this site and the two APIs it uses returned in one afternoon of curl requests (301, 308, 304, 204, 400, 404 and 405), what each means, and the redirect that broke a CORS request.
- 10 CSS Gradient Ideas You Can Copy and Customize · Ten copy-ready CSS gradients (buttons, dark surfaces, progress bars, stripes, glows, gradient text, photo overlays), plus how gradient angles work and how to avoid the muddy grey middle.
- What Is a JWT and How to Decode One Safely · A real token taken apart segment by segment: Base64URL and its missing padding, what exp and iat say in plain dates, why a 5-part token won't decode, and what a decoder can't tell you.