ULID and UUID v4 compared, side by side.
What actually differs, and which one to reach for.
Both give you an identifier you can generate anywhere without coordinating with a database. The difference that matters in practice is ordering: a ULID starts with a millisecond timestamp, so ULIDs generated over time sort in the order they were created. A random UUID does not.
| Dimension | ULID | UUID v4 |
|---|---|---|
| Length | 26 characters | 36 characters with hyphens |
| Encoding | Crockford's base32 (no I, L, O, U) | Lowercase hexadecimal |
| Bits of entropy | 80 random bits per millisecond | 122 random bits |
| Sortable | Yes, lexicographically by creation time | No |
| Timestamp embedded | Yes, millisecond precision | No |
| Standardised | Community spec | RFC 4122 / RFC 9562 |
| Database index locality | Sequential inserts, low fragmentation | Random inserts, page splits |
For new internal primary keys, ULID (or UUID v7, which brings the same time-ordering into the UUID standard) is usually the better default. Stay on UUID v4 when a spec, a database type or an external API expects it, or when exposing creation time would be a leak.
From the maker of MakeUUID