A UUID is a 128 bit identifier used to label records without a central ID allocator.

The letters stand for Universally Unique Identifier. Its standard text form looks like this:

9a74d828-8ed5-422e-a0b1-161fad230523

The 36 characters contain 32 hexadecimal digits in groups of 8, 4, 4, 4 and 12, separated by four hyphens.

Why do we need them?

Most programs need to give things an identity.

A user, an order, an uploaded file, a log line. The classic way is a counter: the first user is 1, the second is 2, and so on.

That works fine when one database hands out the numbers.

It breaks as soon as two systems create records at the same time without talking to each other. Both will hand out the number 42 and you now have a conflict.

A UUID lets machines generate IDs independently.

With a cryptographic random source, v4 collisions are extremely unlikely, but they are possible. There is no central authority, no lock and no network call.

A device can generate IDs without a central allocator. Enforce uniqueness where your application requires it.

How big is 128 bits?

128 bits gives about 340 undecillion possible values. Written out that is 340 followed by 36 zeros.

A random v4 UUID uses 122 of those bits for randomness, which still leaves about 5.3 undecillion values.

If you generated a billion of them every second, nonstop, it would take about 86 years before a repeat became as likely as not. The risk is small, but your storage should still enforce uniqueness.

We look at the actual math in Can Two UUIDs Collide?.

Reading the format

Most of the digits are either random or derived from a timestamp, but two small pieces carry meaning:

The version digit. The first character of the third group tells you which algorithm made the UUID. In the example above it is a 4, so this is a version 4 random UUID. The version helps you decide whether the value carries time or random data.

The variant digits. RFC variant UUIDs use 8, 9, a or b as the first character of the fourth group. Nil and Max are special values with different patterns.

Everything else depends on the version. A version 4 UUID is 122 bits of randomness.

A version 7 UUID starts with a millisecond timestamp, so values with later encoded timestamps sort after earlier ones.

A version 1 UUID combines a timestamp with a node field, which may use a hardware address or a generated value. Our guide to all UUID versions goes through each one.

Where UUIDs are used

Database primary keys, especially when rows are created on many servers or on client devices before they reach the database.

API resource IDs. They identify a record without using its sequential row number. Keep authorization checks separate from the identifier.

File and asset names in object storage, with low collision risk. Use a storage condition that rejects an existing name to prevent overwrites.

Trace IDs and message IDs in distributed systems where requests hop across many services.

Hardware and software identifiers. Windows uses them everywhere under the name GUID, which is the same thing. See UUID vs GUID.

Where UUIDs are a poor fit

They are not free.

A UUID takes 16 bytes of storage against 8 for a 64 bit integer, and 36 bytes when stored as text. They are hard for humans to read aloud or type.

Random ones also scatter writes across a database index, which hurts insert performance on large tables.

If you are choosing a primary key, read Should You Use UUIDs as Primary Keys? before deciding.

The standard behind them

UUIDs were standardised in RFC 4122 in 2005.

In 2024 that document was replaced by RFC 9562, which kept the old versions and added versions 6, 7 and 8. When someone says a UUID is "RFC compliant" they mean it follows the layout in that document.

Try one

The fastest way to get a feel for UUIDs is to generate a few.

Our free UUID generator makes v1, v3, v4, v5, v6 and v7 in your browser, one at a time or up to 1000 in a batch. Notice how the v7 ones share the same leading digits when generated close together, while v4 ones look completely unrelated.

Paste any of them into the validator and decoder to see the version and, for v7, the timestamp inside.