UUID vs ULID: what's the difference?
Both are 128-bit identifiers. The real differences are text encoding, sortability guarantees, and ecosystem support — and UUID v7 changed the debate.
Side by side
| UUID (v4/v7) | ULID | |
|---|---|---|
| Size | 128 bits | 128 bits |
| Text form | 36 chars, hex + hyphens | 26 chars, Crockford base32 |
| Time-sortable | v7: yes / v4: no | Yes (48-bit ms timestamp) |
| Case sensitivity | Lowercase canonical | Case-insensitive |
| Native DB column type | uuid in PostgreSQL, SQL Server, etc. | None — stored as text or bytes |
| Standard | IETF RFC 9562 | Community spec (no RFC) |
What ULID got right
ULID appeared in 2016 to fix v4's biggest operational pain: random keys wreck database index locality. Its layout — a 48-bit millisecond timestamp followed by 80 random bits — makes IDs sort by creation time. The compact, URL-safe base32 encoding is also genuinely nicer to read and paste than hex-with-hyphens.
Why UUID v7 changed the calculus
UUID v7 (standardized in RFC 9562, 2024) adopts essentially the same timestamp-plus-random layout — inside a standard UUID. That means you get ULID's index-friendly ordering while keeping everything the UUID ecosystem already gives you: native uuid column types, driver support, validation in every language, and tooling that has existed for twenty years.
Unless the shorter base32 text form is specifically valuable to you (e.g. user-facing reference codes), v7 now covers ULID's main use case with less friction.
Recommendation
- Greenfield system, standard databases → UUID v7. Native column types and universal library support win.
- Human-facing short codes → ULID's 26-char case-insensitive form is easier to read aloud and type.
- Existing ULID codebase → no urgent reason to migrate; the binary layouts are compatible enough that conversion is possible later.
Need IDs now? Generate time-ordered UUID v7 or any other UUID version instantly in your browser.