MeridianMERIDIAN

ULID

technology.identifier.ulid

Universally Unique Lexicographically Sortable Identifier. 26-character Crockford Base32 string encoding a 48-bit timestamp and 80 bits of randomness.

Casts to
VARCHAR

Shape

Pattern
^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$
ValueLengthShape
01ARZ3NDEKTSV4RRFFQ69G5FAV26matches
01H5J3XZQK000000000000000026matches
01FWHE4G8R2SXHM3F07YR3FW0T26matches
01ARZ3NDEKTSV4RRFFQ69G5FA25rejected: one character short

Background

Origin

ULID stands for Universally Unique Lexicographically Sortable Identifier, a format set out in the ulid/spec repository on GitHub.[1] The ULID specification notes that UUID v4 provides no other information than randomness, which can cause fragmentation in many data structures.[1] The ULID specification describes itself as the current specification of ULID as implemented in the ulid/javascript library.[1] The ulid/javascript package names Alizain Feerasta as its author.[2] The ULID specification says the format was partly inspired by posts on Instagram's engineering blog and Firebase's blog.[1] RFC 9562 lists ULID first among the 16 implementations analysed while its specification was being prepared.[3]

A ULID is made of a 48-bit timestamp followed by 80 bits of randomness.[1] The ULID timestamp is UNIX time in milliseconds.[1] The ULID specification says the timestamp won't run out of space until the year 10889 AD.[1] In the canonical ULID string, the first 10 characters encode the timestamp and the remaining 16 encode the randomness.[1] ULIDs are canonically encoded as a 26-character string, as opposed to the 36-character UUID.[1][4] ULID uses Crockford's Base32, at 5 bits per character.[1] Crockford's Base32 alphabet leaves out the letters I, L, O and U.[1][5] Douglas Crockford's Base 32 page says I and L are left out because each can be confused with 1, and O because it can be confused with 0.[5] Douglas Crockford's Base 32 page gives accidental obscenity as the reason for leaving out U.[5] In binary, a ULID is 16 octets, with each component encoded most significant byte first.[1]

Use

The ULID specification sorts ULIDs in lexical order, left-most character first, using the default ASCII character set.[1] The ULID specification says that within the same millisecond, sort order is not guaranteed.[1] In the ULID specification's monotonic mode, when the same millisecond is detected the random component is incremented by 1 bit in the least significant bit position.[1] Sort on a ULID column for a rough creation order, but do not lean on it to order rows that may share a millisecond, and treat the decoded time as a hint set by whichever system minted the ID rather than as an audit timestamp. (Meridian's view)

Laravel's Eloquent ORM can give a model ULID primary keys through its HasUlids trait.[6] Laravel's documentation describes ULIDs as lexicographically sortable for efficient database indexing.[6] Symfony's documentation says using ULIDs as primary keys is usually not recommended for performance reasons.[4] Keep ULIDs as text when you load them, and if a ULID column will not join against another table, check whether the other side holds the same identifiers in a different form, such as a UUID-style string or raw bytes. (Meridian's view)

Detection notes

Crockford Base32 excludes I, L, O, U to avoid ambiguity. Always uppercase. First 10 chars encode millisecond timestamp.

Use it

CLI · DuckDB
$ finetype infer -i "01ARZ3NDEKTSV4RRFFQ69G5FAV" --mode column
→ technology.identifier.ulid

SELECT ft_infer('01ARZ3NDEKTSV4RRFFQ69G5FAV');
-- → 'technology.identifier.ulid'
Cast expression
CAST({col} AS VARCHAR)

Schema

https://meridian.online/schemas/technology.identifier.ulid · Frictionless type string

finetype taxonomy technology.identifier.ulid -o json-schema

Type Registry