For years, the answer to "what should I use for an ID?" was simple: UUID v4. It is random, collision-resistant, supported everywhere, and works as a primary key in any database. But in 2024 the IETF published RFC 9562, which superseded RFC 4122 and formalised a new family of time-ordered UUID formats — including UUID v7. At the same time, formats like ULID and NanoID have matured into production-ready alternatives. So in 2026, the answer is no longer obvious.
This guide compares the four formats most likely to land on your shortlist, explains the trade-offs that matter in production, and gives you a decision tree at the end.
1. UUID v4: the random standard
UUID v4 gives you 122 bits of cryptographically secure random data inside a 128-bit UUID frame. The probability of a collision is astronomically low — roughly 1 in 5.3 × 1036 — so you can generate them on as many machines as you want without coordination.
The catch shows up at the database layer. When you use UUID v4 as a primary key on a clustered index (the default for MySQL InnoDB, and the recommended pattern for many PostgreSQL designs), every new insert lands at a random position in the index. Once your table outgrows RAM, that means random disk I/O on every insert, page splits, and steadily worsening write throughput. This is the classic "UUIDs are slow" complaint — and it's real.
2. UUID v7: the new default (RFC 9562, 2024)
UUID v7 fixes the index-fragmentation problem without giving up the UUID format. Its 128-bit layout is:
4 bits — version (0111 = 7)
12 bits — sub-millisecond entropy or random
2 bits — variant (10)
62 bits — random
Because the high bits encode time, UUID v7 values are roughly sortable in insertion order. New rows append to the right side of a B-tree index — same access pattern as an auto-increment integer — while still being globally unique and generatable on any client. RFC 9562 also defines v6 (reordered Gregorian time) and v8 (custom), but v7 is what you actually want for new application code.
Trade-off to know: UUID v7 leaks the creation timestamp. An attacker who sees a v7 ID can recover the millisecond it was generated. For most internal IDs that's fine. For password-reset tokens or invite codes, it isn't.
3. ULID: the time-ordered alternative
ULID predates UUID v7 and solves the same problem in almost the same way. It is also 128 bits — 48-bit Unix millisecond timestamp plus 80 bits of randomness — but its canonical string form is 26 characters of Crockford Base32 rather than a 36-character hex UUID with dashes. That makes ULIDs slightly more compact in URLs and logs, and Crockford Base32 deliberately excludes ambiguous characters (no I, L, O, U) so they're easier to copy by hand.
Because ULID is not an IETF standard, database support is via libraries rather than a native column type. If you're starting a new project in 2026 and have no ecosystem reason to prefer ULID, UUID v7 is the lower-friction choice.
4. NanoID: the URL-friendly short ID
NanoID is built for a different job. The default 21-character ID uses a 64-character URL-safe alphabet (A-Z a-z 0-9 _ -) and provides a similar collision profile to UUID v4 — roughly a 1% chance of collision after generating one billion IDs at 1,000 IDs per second for about 26 years. Because it's shorter and URL-safe, NanoID is the right choice for public-facing identifiers like share URLs, invite codes, and short links, where every character counts.
NanoID is not time-ordered. Don't use it as a primary key for a high-write table unless you keep an explicit created_at column for ordering and pagination.
5. Side-by-side comparison
| Format | Bits | String length | Time-ordered | Standard |
|---|---|---|---|---|
| UUID v4 | 128 (122 random) | 36 (hex + dashes) | No | RFC 9562 / 4122 |
| UUID v7 | 128 (62 random) | 36 (hex + dashes) | Yes (ms) | RFC 9562 |
| ULID | 128 (80 random) | 26 (Base32) | Yes (ms) | Community spec |
| NanoID | ~126 (default) | 21 (URL-safe) | No | Library convention |
6. Decision tree: which one should you use?
- Database primary key, new project → UUID v7. Standard, time-ordered, and your database driver almost certainly already speaks UUID.
- Database primary key, existing UUID v4 schema → Stay on UUID v4 unless you have a measurable index-fragmentation problem. Migrations are expensive.
- Public-facing share link, invite code, short URL → NanoID. Shorter, URL-safe, no time leakage.
- Password reset token, email verification → UUID v4 or NanoID. Not v7 or ULID — you don't want the token to leak its creation time.
- Distributed event log, append-only timeline → UUID v7 or ULID. Time-ordering is exactly what you want.
- Existing ULID codebase → Keep using ULID. It still works fine.
Need to generate a UUID right now?
DevToolKit's free UUID Generator runs entirely in your browser using the Web Crypto API — no data is sent to any server. Generate single or bulk UUIDs in one click.
Open UUID Generator →Frequently asked questions
Q. Is UUID v4 still safe to use as a primary key?
A. Yes — UUID v4 still gives you cryptographically random 122-bit identifiers and is supported everywhere. The downside is that random insertion order causes B-tree index fragmentation in databases like MySQL InnoDB and PostgreSQL. For new systems where you control the schema, UUID v7 (time-ordered, standardised in RFC 9562) is usually a better default.
Q. What changed in RFC 9562?
A. Published in May 2024, RFC 9562 supersedes RFC 4122 as the authoritative UUID specification. It formalises three new versions: v6 (reordered Gregorian time), v7 (Unix epoch time + random), and v8 (custom). UUID v7 is the most important addition for application developers because it gives you the same 128-bit format as v4 while remaining roughly sortable by creation time.
Q. Should I use ULID or UUID v7?
A. They are functionally similar — both are 128-bit, time-ordered identifiers. ULID has a more compact 26-character Crockford Base32 representation and slightly older library support. UUID v7 has the advantage of being an IETF standard, native database UUID column types, and existing tooling. For new code in 2026, prefer UUID v7 unless you specifically need ULID's string format or are working in an ecosystem where ULID is already established.
Q. What about NanoID?
A. NanoID is shorter (21 characters by default) and URL-safe, making it ideal for public-facing identifiers like share links or invite codes. It is not time-ordered and has roughly the same collision resistance as UUID v4 at default length. Don't use it as a database primary key in high-volume tables unless you also store a separate created_at column for ordering.
Q. Are these IDs guessable?
A. UUID v4 and the random portion of UUID v7/ULID are generated from a cryptographically secure random source (Web Crypto, /dev/urandom, etc.) so they're not practically guessable. However, UUID v7 and ULID leak the creation timestamp, which can reveal usage patterns. For tokens that must hide creation time — password reset links, invite codes — use UUID v4 or NanoID, not v7 or ULID.
References
- IETF RFC 9562 — Universally Unique IDentifiers (UUIDs), May 2024 (supersedes RFC 4122)
- IETF RFC 4122 — A Universally Unique IDentifier (UUID) URN Namespace (historical)
- ULID specification —
github.com/ulid/spec - NanoID —
github.com/ai/nanoid - Crockford Base32 —
crockford.com/base32.html - MDN Web Docs — Crypto.randomUUID()
Note: This guide is intended as a general technical overview. Specific schema and migration decisions depend on your database engine, query patterns, and existing code. Benchmark on your own workload before changing identifier strategy in production.
About the DevToolKit Editorial Team
DevToolKit's editorial team is made up of working software developers who use these tools every day. Every guide is reviewed against primary sources — IETF RFCs, W3C/WHATWG specifications, MDN Web Docs, and project repositories on GitHub — before publication. We update articles when standards change so the guidance stays current.
Sources we cite: IETF RFCs · MDN Web Docs · WHATWG · ECMAScript spec · Official project READMEs on GitHub