These are identifiers, not credentials. They are designed to be unique without coordination, which is a different property from being unguessable. The distinction matters: a UUID v4 has 122 random bits and would be a perfectly strong secret, but a UUID v7 has only 74, and a UUID v1 leaks its creation time. Never assume an identifier is safe to use as a bearer token.
Choosing between them
| Type | Length | Random bits | Sortable | Best for |
|---|---|---|---|---|
| UUID v4 | 36 | 122 | No | The default when you do not need ordering |
| UUID v7 | 36 | 74 | Yes | Database primary keys |
| UUID v1 | 36 | 60 | Partly | Legacy compatibility only |
| ULID | 26 | 80 | Yes | Sortable IDs that appear in URLs |
| Nano ID | 21 | 126 | No | Short URL-safe IDs |
| Base58 | ~22 | 128 | No | IDs a human might transcribe |
Why v7 exists
Random UUIDs are terrible primary keys. Each insert lands at a random point in the B-tree index, which fragments pages, destroys cache locality and inflates write amplification. On a large table the difference against a sequential key is dramatic.
UUID v7 fixes this by putting a 48-bit millisecond timestamp in the high bits, so new rows sort to the end of the index like an auto-increment integer, while keeping enough randomness to stay unguessable within a millisecond. If you are choosing an ID for a table today and do not have a specific reason otherwise, v7 is the answer.
The cost is that a v7 reveals when the record was created. For most rows that is already visible in a created_at column. For something like an invitation token it may not be acceptable.
Why v1 is discouraged
A true UUID v1 embeds the host's MAC address, which identifies the machine that generated it — a genuine privacy and fingerprinting problem. This generator produces v1-shaped values with a randomised node ID and the multicast bit set, as RFC 4122 §4.5 permits, because a browser cannot read a MAC address and should not want to. Use v7 instead; it gives you the same time ordering without the baggage.
Never use one as a secret
The recurring mistake is a password-reset link containing a UUID, or an "unguessable" object URL keyed by v4. Even where the entropy is technically adequate, identifiers get logged, indexed, sent in Referer headers and shared. Use a real token from the random key generator, give it an expiry, and make it single-use.
Frequently asked questions
Is UUID v4 unique enough to never collide?
For practical purposes, yes. At 122 random bits you would need to generate roughly a billion UUIDs per second for 85 years to reach a 50% chance of a single collision. Collisions are not the risk; a weak random source is, which is why this uses crypto.randomUUID.
Should I use UUID v7 or ULID?
They encode the same idea. Choose v7 if your database has a native UUID type, which gives you 16-byte storage and built-in tooling. Choose ULID if the identifier appears in URLs, where its 26-character Crockford Base32 form is shorter and avoids ambiguous characters.
Can I use a Nano ID as an API key?
At the default 21 characters it carries 126 bits, which is technically sufficient. But it has no prefix, so scanners cannot recognise it and engineers cannot tell what it is. Use a prefixed key from the custom prefix builder instead.
Does UUID v7 leak information?
It reveals the creation time to the millisecond. That is usually harmless for database rows and occasionally not — a v7 used as a public identifier tells anyone who sees it exactly when the record was made, and lets them infer creation order and volume.