ULIDs (Universally Unique Lexicographically Sortable Identifiers) take up the same 128 bits as a UUID, but reserve the first 48 for a timestamp, so they can be sorted by creation time. Michael Drogalis, creator of ShadowTraffic, made the case in a LinkedIn post with a blunt recommendation: anyone using UUIDs should consider swapping them for ULIDs. The discussion in the comments shows the choice comes with trade-offs.
Key points on ULIDs versus UUIDs in 30 seconds
- A ULID has 128 bits, just like a UUID: 48 for a millisecond timestamp and the other 80 random bits.
- It is written as 26 Crockford Base32 characters, with no hyphens, and sorts alphabetically by time.
- As a primary key, it avoids the index fragmentation caused by random UUIDv4 values.
- On the downside, it reveals when each record was created, and machine clocks do not guarantee exact ordering in distributed systems.
The idea is simple. A version 4 UUID, the most common kind, is a string of random bits: it identifies something without collisions but says nothing about when it was generated. A ULID, according to its specification, encodes the creation time in milliseconds since 1970 in its first 48 bits and keeps 80 random bits to avoid clashes between identifiers created in the same millisecond. The result is written as 26 characters in Crockford Base32, which is case-insensitive and skips easily confused letters such as I, L, O and U.
How to read a ULID
Drogalis explains it with an example: 01HX2AY3TN3M5ZFA5TG2WZJZ6G. The first 10 characters (01HX2AY3TN) are the timestamp and the remaining 16 (3M5ZFA5TG2WZJZ6G) are the random value. To tell which of two ULIDs was generated first, you only need to compare that first part; because the encoding preserves order, you do not even need to decode it, since an alphabetical sort gives the same result.
The diagram accompanying the post is illustrative and its figures do not fully match each other. Decoded with the Crockford Base32 table, the prefix 01HX2AY3TN corresponds to 4 May 2024 at 17:37:54 UTC, not the date shown in the graphic. In practice, ULID libraries include functions to extract the timestamp, and implementations exist for almost every mainstream language.
Why it matters for the database
The most practical benefit for administrators shows up when ULIDs are used as primary keys. In the comments, engineer Pascal Lüscher summed up the problem: with UUIDv4 as a clustered index, the database engine has to keep rearranging the table, because every insert lands at a random point in the index. With ULIDs, or with UUIDv7, new rows are almost always appended at the end, reducing fragmentation and page splits.
It is worth remembering that the UUID standard already offers an equivalent option. RFC 9562, published in 2024, defines UUIDv7, which also starts with a 48-bit Unix timestamp in milliseconds and fits into the UUID column types of databases such as PostgreSQL. For teams whose schema is already UUID-based, it can be a less disruptive change than moving to ULIDs, which are usually stored as 26-character text or as 16-byte binary.
What came up in the comments
Not everyone was convinced. Peter Mahon, a site reliability engineer (SRE), saw no clear advantage over a UUIDv4 plus a UTC timestamp column beyond the space saving, and warned that embedding the timestamp gives away some privacy and security: anyone who sees an identifier knows when it was created. Sean Michael Kelly replied that a UUIDv4 plus a date means two values where often only one fits, and that ULIDs avoid having to combine them.
Ben Meier, a platform engineer, pointed out a practical detail: because ULIDs have no hyphens, you can select a whole one with a double click, which he appreciates in day-to-day operations. Drogalis himself ended his post with a warning any administrator of distributed systems knows well: clocks on different machines are never perfectly synchronised, so ordering between ULIDs generated on different servers is not reliable to the millisecond. Within a single machine, the specification provides a monotonic mode that increments the random part when several identifiers are generated in the same millisecond.
Frequently asked questions
What is a ULID?
A 128-bit unique identifier that combines a 48-bit timestamp with 80 random bits and can be sorted by creation time.
How does a ULID differ from a UUIDv4?
A UUIDv4 is fully random. A ULID includes its creation time, is written as 26 Base32 characters without hyphens and sorts alphabetically by time.
ULID or UUIDv7?
Both start with a 48-bit timestamp. UUIDv7 is a standard (RFC 9562) that fits existing UUID columns; ULID uses a more compact text representation.
Do ULIDs have any drawbacks?
They reveal when each record was created and, in distributed systems, ordering across machines depends on their clocks being in sync.
Sources:
