f47ac10b-58cc-4372-a567-0e02b2c3d479 looks like a strange thing to use as an ID when a plain
number like 1, 2, 3 would be so much shorter. But that strangeness is
the entire point — UUIDs solve a specific problem that simple counting numbers can't.
What UUID actually stands for
UUID means Universally Unique Identifier — a 128-bit value, conventionally written as 32 hexadecimal
characters grouped into five sections separated by hyphens:
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx. The "M" position identifies which UUID version was used to
generate it, and the "N" position encodes a related detail called the variant.
The problem it solves: generating IDs without central coordination
A traditional auto-incrementing ID (1, 2, 3, 4...) requires one central authority handing out the next number, which works fine for a single database, but breaks down the moment you have multiple independent systems that each need to generate IDs on their own, without checking in with each other first. Imagine three different microservices, each inserting new "order" records into their own local storage before syncing later. If they all used simple incrementing integers starting from 1, you'd get collisions immediately: three different orders, from three different services, all claiming to be "order #1."
UUIDs solve this by making the ID itself carry enough randomness (or, in some versions, enough unique input like a timestamp and machine identifier) that two independently generated UUIDs can be created at the same moment, on opposite sides of the planet, with no coordination between them, and still not collide.
The version that matters most today: UUID v4
There are several UUID versions, each generating the 128 bits differently, but version 4 is by far the most common in modern software. UUID v4 is (almost) pure randomness — of the 128 total bits, 122 are randomly generated, and the remaining 6 are fixed to identify the UUID as version 4 and set the correct variant. That's it. No timestamp, no machine address, no embedded information at all — just 122 bits of randomness.
Just how unlikely is a collision, really?
With 122 random bits, the number of possible UUID v4 values is 2122 — an almost incomprehensibly large number. To put it in perspective: to have even a 50% chance of one single collision occurring anywhere, you'd need to generate roughly 2.7 quintillion UUIDs. Generating a billion UUIDs a second, it would still take a meaningfully long time to reach even a small probability of a single collision. For essentially every real-world application — database keys, session tokens, file names, test data — the probability of an accidental collision is so far below the probability of, say, a hardware failure corrupting your data anyway, that it's not a practical concern.
Other UUID versions, briefly
- UUID v1 — based on the current timestamp plus the generating computer's network card address (MAC address). Guarantees uniqueness through those specific inputs rather than pure randomness, but can leak information about when and where the UUID was generated, which matters for privacy in some contexts.
- UUID v3 and v5 — deterministic, not random at all. Both generate a UUID by hashing a namespace identifier plus a name (v3 uses MD5, v5 uses the stronger SHA-1). The same namespace and name always produce the exact same UUID, which is useful when you specifically want a repeatable, predictable identifier for a given input.
- UUID v7 — a newer version designed to be both random and roughly sortable by creation time, addressing a real downside of v4 (pure randomness means UUIDs don't sort in any meaningful order, which can hurt database index performance at scale).
When a UUID is the right choice
- Distributed systems generating IDs independently. The original problem UUIDs were built to solve.
- Not wanting to expose how many records exist. Sequential integer IDs leak information — if you see order #4,582, you can guess roughly how many orders exist. A UUID reveals nothing.
- Merging data from multiple sources. If two databases might each generate their own IDs and later need to be combined, UUIDs make collisions during that merge extremely unlikely.
- Idempotency keys. A client can generate a UUID before submitting a request, and safely retry with the same UUID if the request seems to have failed, letting the server recognize and ignore an accidental duplicate.
When a simple integer is still the better choice
UUIDs aren't free. They take 16 bytes of storage versus 4 or 8 for a typical integer, they're not naturally sortable by creation order (with v4 specifically), and being 36 characters long makes them slower to type, compare, and index at very large scale compared to a plain number. For a single, non-distributed database where you fully control ID generation and don't need to hide how many rows exist, a simple auto-incrementing integer is often still the simpler, more efficient choice.
The one-sentence version
A UUID trades a small amount of size and readability for the ability to generate a virtually guaranteed-unique ID anywhere, by anyone, with zero coordination required — and that trade is worth it exactly when coordination is the thing you don't have.