ULID vs UUID
Random UUIDs are convenient until they meet a database index. Every insert lands at a random position, the index fragments, and write performance degrades on large tables. ULID was designed to keep the uniqueness of a UUID while restoring the ordering you lose with random values.
What a ULID is
A ULID is a 128 bit identifier, the same width as a UUID, but it is laid out in two parts. The first 48 bits are a Unix timestamp in milliseconds. The remaining 80 bits are random. Encoded for display, it becomes a 26 character string.
01ARZ3NDEKTSV4RRFFQ69G5FAV
|----------|---------------|
timestamp randomness
(10 chars) (16 chars)
Because the timestamp sits in the high bits and the encoding preserves order, ULIDs sort the same way whether you compare them as raw bytes or as text. Two ULIDs generated in the same millisecond fall back to comparing their random portions, so they stay distinct but their relative order within that millisecond is arbitrary.
Lexicographic sorting and index locality
This is the main reason to choose ULID. A random v4 UUID scatters inserts across the full width of a B tree index, which causes page splits and poor cache behavior. A ULID inserted now is always greater than one inserted a second ago, so new rows append near the right edge of the index. Reads that filter or page by creation order can often use the identifier directly instead of a separate timestamp column.
UUID version 7 offers the same benefit in the UUID format, so if your stack already expects UUIDs, v7 may be the simpler path. See UUID v1 vs v4 for where v7 fits.
The Crockford base32 alphabet
ULIDs are encoded with Crockford base32 rather than hexadecimal. The alphabet uses digits and uppercase letters but deliberately omits I, L, O, and U. Dropping I, L, and O avoids confusion with 1 and 0, and dropping U reduces the chance of forming unwanted words. Decoders treat the excluded letters leniently, mapping a typed O to 0, for example, which makes ULIDs friendlier to read aloud or copy by hand than a raw UUID.
Base32 is also more compact on screen: 26 characters against the 36 of a hyphenated UUID, while carrying the same 128 bits of information.
The tradeoffs
ULID is not a free upgrade.
- Time leakage: the creation time is embedded and readable, just as with UUID v7. Do not use either where the timestamp is sensitive.
- Ecosystem: UUID has native database types and built in functions almost everywhere. ULID usually arrives as a library and is often stored as text or as a 16 byte binary.
- Monotonicity within a millisecond is only guaranteed if your generator implements the optional monotonic mode.
For classic random identifiers you can generate v4 UUIDs in the UUID & Token Generator, which runs entirely in your browser so nothing you create is transmitted. If you want a shorter random option instead, compare nanoid vs uuid.
The practical takeaway: choose ULID or UUID v7 when index locality and time ordering matter, stay with v4 when you want zero embedded information, and remember the readable Crockford alphabet is part of what makes ULID pleasant to handle.