ULID, and how it maps onto a UUID

ULID7 sectionsUpdated

A ULID is 128 bits printed as 26 Crockford base32 characters: 48 bits of Unix milliseconds followed by 80 random bits. The bits fit a UUID exactly, so converting between the two is a change of alphabet, not of value.

ULID appeared before RFC 9562 had a time-ordered layout, and it solved the same problem in a shorter, case-insensitive text form. This page covers what is inside one and how it lines up with a UUID v7.

ULIDcomputed by the converter itself
in01890a5d-ac96-774b-bcce-b302099a8057out01H455VB4PEX5VSKNK084SN02Q

A v7: the leading milliseconds survive the conversion

in00000000-0000-0000-0000-000000000000out00000000000000000000000000

Nil: 26 zeros in base32

inffffffff-ffff-ffff-ffff-ffffffffffffout7ZZZZZZZZZZZZZZZZZZZZZZZZZ

Max: the largest ULID there is

Open the converter: ULIDNothing you paste leaves the browser.
On this page (7)

What a ULID is made of#

PartBitsCharactersWhat it holds
timestamp4810Unix milliseconds, most significant first
randomness8016Random, or a counter incremented within the millisecond

Ten characters of base32 encode 50 bits, two more than the timestamp has, so the first character of a ULID never exceeds 7 and only reaches 7 once the 48-bit millisecond clock runs out in the year 10889. That is why every ULID you have seen starts with a digit, and why the largest one that exists is 7ZZZZZZZZZZZZZZZZZZZZZZZZZ.

The alphabet#

Crockford base32 drops I, L, O and U: I and L look like 1, O looks like 0, and U was removed to avoid accidental words. Decoding is case-insensitive, so a ULID read aloud, typed from a screenshot or shouted across a room survives the trip better than hex does.

ULID against UUID v7#

ULIDUUID v7
Text length2636
AlphabetCrockford base32, case-insensitivehex with hyphens
Timestamp48 bits of Unix ms48 bits of Unix ms
Random bits8074
Fixed bitsnone6: version and variant
Fits a native uuid columnafter conversiondirectly

The six fixed bits are the whole difference in content. A ULID converted to a UUID keeps its bits, so the result usually reports an arbitrary version: a valid 128-bit value, but not a valid v7. Converting the other way is lossless in both directions as long as you accept that.

RFC 9562 § 6.11 · SortingSorting, the property both formats are built around

Monotonicity inside one millisecond#

The ULID specification suggests incrementing the random component when several identifiers are made in the same millisecond, so that they still sort in creation order. Not every implementation does it, and two ULIDs from the same millisecond may otherwise come back in arbitrary order, the same caveat as rand_a in a v7.

Questions people actually ask#

Can I convert a ULID to a UUID?

Yes, both ways. Both are 128 bits; only the text encoding differs. A converted ULID will not usually be a valid v7, because a ULID has no version bits.

Why does every ULID start with a digit?

Ten base32 characters carry 50 bits but the timestamp is only 48, so the two extra bits are always zero and the leading character stays between 0 and 7.

Is a ULID case sensitive?

No. Crockford base32 decodes case-insensitively and omits I, L, O and U to avoid confusion with 1 and 0.

Browse the reference