Every database row, uploaded file, and API resource needs an identifier, and the humble auto-incrementing number breaks down the moment your system grows beyond one server. That is the problem UUIDs were invented to solve: a 128-bit identifier anyone can generate, anywhere, without asking permission or checking a central list.

What a UUID actually is

A UUID (universally unique identifier) is a 128-bit number, usually written as 32 hexadecimal digits split into five groups by hyphens: 123e4567-e89b-12d3-a456-426614174000. The format is 8-4-4-4-12 characters, and the hyphens are cosmetic — the value is the same with or without them. A few of those hex digits are not random at all: they encode the UUID's version and variant, which is how a system can tell at a glance how the ID was made.

The versions that matter

There are eight defined versions, but in practice you will meet four:

If you are starting a new project today, version 7 is usually the best default. It keeps the decentralization of version 4 while behaving much better in indexes, because new rows land near each other instead of scattered randomly through the table.

How unique is "unique," really?

A version 4 UUID has 122 random bits, which means there are about 5.3 x 1036 possible values. The birthday paradox still applies: collisions become likely only after generating roughly 2.7 quintillion IDs. To put that in concrete terms, if you generated one billion UUIDs per second, you would need to run for about 85 years before reaching even a 50 percent chance of a single collision.

In practice, that means you can treat UUIDs as unique without checking. Two phones creating records offline, two servers in different data centers, and a developer's laptop can all mint IDs independently, and the chance that any two collide is smaller than the chance of a hardware fault corrupting the data anyway. The one exception is a broken random-number generator — if your source of randomness is weak, all bets are off, which is why you should always use your platform's cryptographic random generator rather than rolling your own.

UUID vs. auto-increment ID: the real tradeoffs

Auto-increment integers are small, fast to index, and easy to read, and they are still the right choice for a single database that will never be merged or exposed. But they carry three costs that UUIDs avoid:

UUIDs solve all three: they are unguessable, merge-safe, and generatable anywhere. The costs are real too — 16 bytes instead of 4 or 8, uglier URLs, and (for version 4) random insertion order that fragments database indexes. Version 7 largely answers the indexing complaint, and storing UUIDs as binary rather than 36-character strings answers the size complaint.

Worked example: merging two customer databases

Imagine two regional stores, each with its own system, each assigning customer numbers starting at 1. Store A has customers 1 through 40,000; store B has customers 1 through 25,000. Merge them and 25,000 IDs collide, forcing a remapping project that touches orders, invoices, and support tickets.

Now imagine both stores had used UUIDs from day one. Every customer ID is globally unique by construction, so the merge is a simple union of tables — no remapping, no broken foreign keys, no weekend migration. This is the scenario that justifies UUIDs on its own: the cost of adopting them is small, but the cost of switching to them later, after collisions already exist, is large.

When not to use a UUID

UUIDs are not the answer to every identification problem. Skip them when the ID is user-facing and needs to be typed or spoken — a support ticket number like 847291 beats a 36-character string every time. Skip them when you need a short, memorable code, such as a coupon or invitation code, where a purpose-built short code is better. And never use a UUID as a secret: version 4 IDs are random but they are designed to be identifiers, not passwords or API keys, and they may appear in logs, URLs, and error messages.

For database primary keys, the practical rules are simple: use version 7 for new tables, store the value as binary if your database supports it, and always generate IDs with a well-tested library. Do that, and you get globally unique, merge-safe, unguessable identifiers at a cost your system will never notice.

AdvertisementAd slot: in-content

Frequently asked questions

Are UUIDs guaranteed to be unique?

No, but the odds are so overwhelmingly in your favor that the distinction rarely matters. A version 4 UUID draws from 122 random bits, so you would need to generate about 2.7 quintillion of them before a collision becomes likely. For any real system, that is effectively unique, provided your random-number generator is sound.

Should I use UUID version 4 or version 7?

For new projects, version 7 is usually the better default. It keeps version 4's randomness but adds a timestamp prefix, so new IDs sort roughly by creation time and database indexes stay efficient. Version 4 remains the right choice when you specifically want no ordering information embedded in the ID.

Can I use a UUID as a password or API key?

No. A UUID is an identifier, not a secret, and it is likely to show up in URLs, logs, and error messages where secrets should never appear. Use a dedicated secret generator with sufficient entropy for passwords and API keys, and keep those values out of identifiers entirely.

Should a UUID be the primary key of my database table?

It can be, and version 7 makes it practical by keeping inserts roughly ordered. Store the UUID as binary (16 bytes) rather than a 36-character string to keep indexes small, and measure before worrying: for most applications the performance difference versus an integer key is negligible.