ULID generator: identifiers that sort by time

26-character sortable IDs: a timestamp plus 80 random bits.

How a ULID is structured

A ULID is 128 bits: 48 bits of time in milliseconds and 80 bits of randomness. In text it takes 26 Crockford Base32 characters: the first 10 encode the time, the remaining 16 the random part. The alphabet deliberately omits I, L, O and U: they are easy to confuse with one, zero and each other when read off a screen.

There is no version or variant as in a UUID — this is a different family. What it does have is sortability: strings created earlier compare as smaller. For primary keys this gives the insert locality in a B-tree that random UUID v4 lacks.

Monotonicity within a batch

Thousands of values can be created within one millisecond, and they will share the same timestamp. To keep the order intact, the generator increments the random part for each successive value: the batch comes out strictly increasing. Formally this is a property of the implementation rather than a guarantee of the standard, but for practical tasks it is exactly what you need.

Where to store it

In PostgreSQL a ULID goes into char(26) or a binary column, but not into the uuid type: they are different formats, even though both are 128 bits. In MySQL and SQL Server, the 16 bytes of the binary representation are cheaper for the index than 26 text characters; the choice depends on what matters more — readability in the console or index size.

A ULID reveals the approximate creation time. If that is undesirable, UUID v4 or NanoID is a better fit for public links.

Frequently asked questions

How is a ULID different from UUID v7?

Both are 128-bit and sortable. A ULID is 48 bits of time and 80 random bits in 26 Base32 characters; v7 is an RFC standard with 74 random bits in 36 characters.

Why does the alphabet leave out I, L, O and U?

Crockford Base32 drops the characters people confuse when reading: I and L with 1, O with 0, U with V.

Is a ULID monotonic?

Within one batch, yes: when the millisecond is the same, the random part is incremented, so the values increase and sort as strings.

Checked: 26 October 2026. For reference only — the result depends on the material and the skill of the installer.