Engineering guide

What Is a UUID? Versions, Format, and When to Use Each

What is a UUID? Learn the 36-character format, how UUID v4 and v7 differ, when to use each, how unlikely collisions are, and why UUIDs are not secrets.

Two rows of grouped identifier blocks, one randomly shaded beside a dice and one shaded in order beside a clock

A string like 36b8f84d-df4e-4d49-b662-bcde71a8764f turns up in URLs, database rows, API responses, and log files. It is a UUID, and it solves a surprisingly hard problem: how can many computers create identifiers at the same time, without talking to each other, and still avoid ever handing out the same one twice?

This guide explains what a UUID is, how the format works, how version 4 and version 7 differ, how unlikely a collision really is, and why a UUID is an identifier but not a secret. It draws on the IETF's RFC 9562, which defines UUIDs, and on Mozilla's documentation, linked at the end.

The short answer: use a random version 4 UUID as a general-purpose unique ID, use version 7 when you want IDs that sort by creation time, such as database primary keys, and never treat any UUID as a password or access token.

What is a UUID?

UUID stands for Universally Unique Identifier. RFC 9562 describes it as a value 128 bits long that is intended to guarantee uniqueness across space and time. Mozilla's glossary describes it as a label used to uniquely identify a resource among all other resources of that type, usually generated locally by computer systems using very large random numbers.

The key benefit is decentralization. As the RFC explains, UUIDs require no central registration process, so any system can generate one on demand, even at very high rates, without asking a central server for the next number. This makes them popular in distributed systems, offline-capable apps, and anywhere data from many sources is merged. The same kind of identifier is called a GUID in Microsoft's terminology.

What does a UUID look like?

The standard text form is 32 hexadecimal digits split into five groups by hyphens, in an 8-4-4-4-12 pattern. That makes 36 characters including the hyphens, and the underlying value is 16 bytes. The RFC's own example is f81d4fae-7dec-11d0-a765-00a0c91e6bf6.

Two digits carry meaning. The first digit of the third group is the version number, so in the sample 36b8f84d-df4e-4d49-b662-bcde71a8764f, which Mozilla shows as an example of a randomly generated UUID, the third group starts with 4 because it is a version 4 UUID. The first digit of the fourth group is 8, 9, a, or b for standard UUIDs, which identifies the variant.

UUID versions at a glance

RFC 9562 defines several versions, each built differently. You will meet versions 4 and 7 most often in new code, but it helps to know what the others are.

  • Version 1: built from a timestamp and a node identifier, historically a network card's MAC address. The RFC warns that MAC addresses pose inherent privacy risks and should not be used within a UUID.
  • Versions 3 and 5: name-based, produced by hashing a namespace and a name, so the same input always gives the same UUID.
  • Version 4: random, with 122 random bits.
  • Version 6: a reordering of version 1 that sorts by time.
  • Version 7: a Unix millisecond timestamp in the most significant 48 bits followed by random data, so values sort by creation time.
  • Version 8: reserved for custom, vendor-specific layouts.
  • Nil and Max UUIDs: special values with all 128 bits set to zero or to one, used as placeholders and range endpoints.

UUID version 4: random identifiers

Version 4 is meant for generating UUIDs from truly random or pseudorandom numbers. Of the 128 bits, 122 are random and the remaining 6 mark the version and variant. Because nothing in it depends on time, hardware, or order, a version 4 UUID reveals nothing about when or where it was created.

In JavaScript, crypto.randomUUID() returns a version 4 UUID built with a cryptographically secure random number generator, as a 36-character string. Mozilla notes that it is available only in secure contexts, meaning HTTPS, and that it has been available across browsers since March 2022. Use it instead of writing your own generator.

UUID version 7: time-ordered identifiers

Version 7 puts a Unix timestamp in milliseconds in the most significant 48 bits and fills the rest with random data. IDs created later therefore sort after IDs created earlier. RFC 9562 points out that this clusters temporally adjacent values together, which improves what it calls database-index locality.

That matters for databases. Random version 4 values scatter new rows across an index, while time-ordered version 7 values append near the end, which generally suits indexes better. The trade-off is that a version 7 UUID contains an approximate creation time that anyone who sees the ID can read, so it is not the right choice when that timing must stay private.

How unlikely is a UUID collision?

A version 4 UUID has 122 random bits, which is about 5.3 × 10^36 possible values. A standard approximation for the chance of any two matching among n random values is n squared divided by twice the number of possibilities. Generating one billion UUIDs gives a collision chance of roughly 9.4 × 10^-20. Even generating one trillion gives about 9.4 × 10^-14.

Mozilla summarizes it by saying that in theory the IDs may not be globally unique, but the probability of duplicates is vanishingly small. These figures assume a good source of randomness, so always generate UUIDs with a cryptographically secure generator, not with Math.random or a home-made routine.

A UUID is an identifier, not a secret

It is tempting to use a UUID as a hard-to-guess link, API key, or reset token. RFC 9562 warns against it in its security considerations: implementations should not assume that UUIDs are hard to guess, and UUIDs must not be used as security capabilities.

For anything that grants access, generate a dedicated token from a cryptographically secure random generator, give it plenty of length, and enforce authorization on the server instead of relying on an unguessable address. Treat the UUID as a label that says which record you mean, nothing more.

Using UUIDs as database primary keys

UUIDs are popular as primary keys because any service can create them independently and records from different systems can be merged without clashes. They also avoid exposing a running count, such as how many customers you have.

They do cost more than small integers: 16 bytes instead of 4 or 8, and bigger indexes. Where your database offers a native UUID or binary type, use it instead of storing the 36-character text, and consider version 7 if you want insertion order to match creation order. Choose version 4 when you need the identifier to reveal nothing about timing.

Which UUID version should you use?

Most choices reduce to two questions: does ordering matter, and is it acceptable to reveal when the ID was created?

  • General unique ID with no ordering needs: version 4.
  • Database primary keys where sorted, time-ordered inserts are useful: version 7.
  • IDs that must not reveal creation time: version 4.
  • A stable ID derived from a name, such as a URL or username: version 5, which always yields the same result for the same input.
  • Anything that grants access, such as a session, reset link, or API key: not a UUID, but a purpose-built secure token.

Common UUID mistakes

Most UUID problems come from expecting them to do more than they promise.

  • Treating a UUID as a secret or as proof that a visitor is allowed to see a record.
  • Generating UUID-like strings with Math.random or a timestamp, which can collide. Use crypto.randomUUID() or a vetted library.
  • Using version 1 and unintentionally exposing a device identifier and a precise timestamp.
  • Publishing version 7 UUIDs and forgetting that they reveal creation time.
  • Comparing UUIDs with inconsistent letter case or braces. Normalize them first.
  • Storing UUIDs as long text in large tables when a compact native type is available.

Worked example: decoding a UUID

You can read a UUID by eye once you know the layout. Take Mozilla's sample 36b8f84d-df4e-4d49-b662-bcde71a8764f. Remove the hyphens and you have 32 hexadecimal digits, which is 16 bytes. The third group, 4d49, starts with 4, so this is a version 4 UUID. The fourth group, b662, starts with b, which marks the standard variant. Everything else is random.

A version 7 UUID is more revealing. Its first 12 hexadecimal digits are a millisecond Unix timestamp. For example, 14 November 2023 at 22:13:20 UTC is 1,700,000,000,000 milliseconds after the epoch, which is 018bcfe56800 in hexadecimal. A version 7 UUID created at that exact instant would therefore begin 018bcfe5-6800-7, followed by random digits, with the 7 marking the version. Anyone who sees the ID can convert the prefix back to a date.

This is the practical meaning of the trade-off described earlier. The same property that makes version 7 sort by creation time also lets outsiders estimate when a record was created, so choose it only when that is acceptable.

A privacy note about online UUID generators

Generating a UUID is a harmless operation, because the value is random and carries no information. The tool still matters if you paste existing IDs, log lines, or records into it. Prefer a generator that runs in your browser or a built-in command, and avoid sending real data to sites you have not verified.

Practical checklist

  • Use crypto.randomUUID() or a vetted library to generate version 4 UUIDs.
  • Choose version 7 when IDs should sort by creation time.
  • Never rely on a UUID as a password, token, or access control.
  • Avoid version 1 so no MAC address or exact timestamp leaks.
  • Store UUIDs in a native UUID or binary column where available.
  • Normalize case and format before comparing UUIDs.
  • Remember that version 7 reveals an approximate creation time.

Research and references

This guide was prepared from the authoritative references below.

  1. RFC 9562: Universally Unique IDentifiers (UUIDs)
  2. MDN Web Docs: Crypto: randomUUID() method
  3. MDN Web Docs: UUID