Quick answer
A ULID (Universally Unique Lexicographically Sortable Identifier) is a 128-bit ID written as 26 Crockford Base32 characters: a 48-bit millisecond timestamp followed by 80 random bits, such as 01ARYZ6S41TSV4RRFFQ69G5FAV. Because the time comes first, ULIDs sort by creation time as plain strings. In Playxoft's ULID generator, choose how many you need, keep Monotonic on to guarantee order within a millisecond, and copy or download the batch.
- Monotonic ordering
- Bulk up to 1,000
- Timestamp decoder
- ULID to UUID
- Crockford validation
- JSON, CSV and SQL lists
- Copy and download
How to use the ULID Generator
- 1Set How many ULIDs you need, from 1 to 1,000.
- 2Keep Monotonic on so ULIDs created in the same millisecond still sort in the order they were made.
- 3Pick the Format: canonical uppercase or Lowercase, quotes, and a list layout such as a JSON array or a CSV column.
- 4Copy the highlighted ULID, or use Copy all and Download for the batch. Click Generate new or press R for fresh ones.
- 5Paste any ULID into the ULID decoder and validator to read its timestamp, or paste a UUID to see it written as a ULID.
What is a ULID?
A ULID is a 128-bit identifier designed to be unique like a UUID but sortable by creation time, defined by the community ULID specification. It has two parts:
01ARYZ6S41 TSV4RRFFQ69G5FAV
└─ timestamp ─┘ └─── randomness ───┘
10 characters 16 characters
48 bits (ms) 80 bitsThe text form uses Crockford Base32: the digits 0–9 and the letters A–Z without I, L, O and U. That makes ULIDs 26 characters long (10 fewer than a hyphenated UUID), case-insensitive, URL-safe without escaping, and easy to read aloud. Because 26 characters hold 130 bits but a ULID has only 128, the first character is always 0–7; the largest possible ULID is 7ZZZZZZZZZZZZZZZZZZZZZZZZZ, which covers timestamps until the year 10889.
Since the timestamp comes first and Base32 digits are in ASCII order, sorting ULIDs as strings sorts them by time. No parsing needed.
ULID vs UUID v7: which should I use?
UUID v7 (standardized in RFC 9562 in 2024) borrowed the ULID idea, so the two are close cousins:
| ULID | UUID v7 | |
|---|---|---|
| Defined by | Community spec on GitHub | IETF standard (RFC 9562) |
| Size | 128 bits | 128 bits |
| Timestamp | 48-bit Unix milliseconds | 48-bit Unix milliseconds |
| Random bits | 80 | 74 (some may be a counter) |
| Text form | 26 characters, Crockford Base32 | 36 characters, hex with hyphens |
| Case | Insensitive, uppercase canonical | Insensitive, lowercase canonical |
| Native database type | None (store as text or 16 bytes) | uuid in PostgreSQL, uniqueidentifier in SQL Server |
| Built-in generators | Libraries only | Python 3.14, PostgreSQL 18, .NET 9 |
Choose UUID v7 when IDs live in a database with a native UUID type, cross system boundaries, or must pass UUID validators. Choose ULID when the string form matters: shorter URLs, file names and log lines, case-insensitive matching, or an existing system already built on ULIDs. Both give you time-ordered inserts and the same index benefits.
What does monotonic mode do?
Within one millisecond, plain ULIDs share a timestamp and differ only in their random part, so a batch created in the same millisecond sorts in random order. The spec's monotonic mode fixes that: when the timestamp has not changed, the generator takes the previous ULID's random part and adds one.
- A batch of 1,000 ULIDs therefore sorts exactly in creation order.
- If the system clock moves backwards, the last timestamp is reused, so the sequence never goes down.
- Overflowing the 80-bit random part within one millisecond is an error per the spec. Because it starts at a random value, that takes about 2^79 increments on average, far beyond any real workload.
The trade-off: in monotonic mode, the next ULID from the same generator is predictable (previous plus one). ULIDs are identifiers, not secrets, so never use them as tokens either way.
Can I store a ULID in a UUID column?
Yes. A ULID and a UUID are both 128 bits, so any ULID can be written in UUID notation and stored in a native uuid column, which takes 16 bytes instead of 26 characters. The decoder above shows this As UUID form for every ULID, and converts the other way when you paste a UUID.
Two caveats. First, the result does not set UUID version or variant bits, so strict validators that require v4 or v7 may reject it. Second, ordering is preserved only if the database compares UUIDs byte by byte from the start, as PostgreSQL does; SQL Server's uniqueidentifier sorts by its last bytes first. Going the other way, a UUID v7 written as a ULID keeps its timestamp, because both put Unix milliseconds in the first 48 bits.
How do I generate a ULID in code?
There is no built-in ULID generator in mainstream runtimes, but well-maintained libraries exist for every language:
// JavaScript — npm install ulid
import { ulid, monotonicFactory } from "ulid";
ulid(); // "01ARYZ6S41TSV4RRFFQ69G5FAV"
const next = monotonicFactory();
next(); // sorted even within one ms
# Python — pip install python-ulid
from ulid import ULID
str(ULID()) # new ULID
ULID.from_str("01ARYZ6S41TSV4RRFFQ69G5FAV").datetime
// Go — github.com/oklog/ulid/v2
id := ulid.Make() // monotonic within the process
fmt.Println(id.String(), ulid.Time(id.Time()))
// C# — dotnet add package Ulid
var id = Ulid.NewUlid();
Guid asGuid = id.ToGuid();To check what a library produced, paste its output into the decoder above: it validates the alphabet, length and first character, and shows the exact timestamp.
Frequently asked questions
Last updated by the Playxoft engineering team.