ULID Generator

Generate ULID identifiers

Why use an ULID instead of an UUID?

ULIDs offer several advantages over UUIDs:

  • Lexicographically sortable
  • Better performance in DBs
  • Shorter and readable (Base32)
Structure of an ULID

An ULID consists of 26 characters:

10 chars for Timestamp | 16 chars for Randomness
Understanding ULIDs
TL;DR

ULID combines a 48-bit timestamp with 80 bits of randomness, producing IDs that are both unique and chronologically sortable.

What is a ULID?

A ULID (Universally Unique Lexicographically Sortable Identifier) is a 128-bit identifier designed to be both globally unique and time-ordered. Created by Alizain Feerasta in 2016, ULIDs address a key limitation of UUIDs: random UUIDs (v4) are not sortable, which causes performance problems when used as database primary keys.

A ULID encodes a Unix timestamp in milliseconds in its most significant bits, followed by cryptographically random data. This means ULIDs generated later are always lexicographically greater than earlier ones — you can sort them as strings and get chronological order for free.

ULIDs are represented as 26-character strings using Crockford Base32 encoding, making them URL-safe, case-insensitive, and more compact than the 36-character UUID format.

ULID Structure

A ULID is 128 bits total, split into two components:

ULID Structure Breakdown The ULID 01ARZ3NDEKTSV4RRFFQ69G5FAV split into a 10-character timestamp portion (48 bits) and a 16-character randomness portion (80 bits). ULID Structure (128 bits, Crockford Base32) 01ARZ3NDEKTSV4RRFFQ69G5FAV 01ARZ3NDEK Timestamp 48 bits (10 characters) Unix time in milliseconds Valid until 10889 AD TSV4RRFFQ69G5FAV Randomness 80 bits (16 characters) Cryptographically random Monotonic within same ms Total: 128 bits = 26 Crockford Base32 characters Lexicographic sort order = Chronological order

The timestamp occupies the first 48 bits (10 Crockford Base32 characters). It stores the number of milliseconds since Unix epoch (January 1, 1970). This gives ULIDs a valid range until approximately the year 10889.

The randomness occupies the remaining 80 bits (16 characters). When multiple ULIDs are generated within the same millisecond, implementations typically increment the random portion monotonically to preserve sort order within the same timestamp.

Crockford Base32 Encoding

ULIDs use Crockford Base32, an encoding alphabet designed by Douglas Crockford that is optimized for human readability:

0123456789ABCDEFGHJKMNPQRSTVWXYZ

Four letters are deliberately excluded:

  • I — confused with 1 or l
  • L — confused with 1 or I
  • O — confused with 0
  • U — can form accidental profanity

This makes ULIDs safer to read aloud, transcribe manually, and use in URLs. The encoding is case-insensitive, so 01ARZ3NDEK and 01arz3ndek represent the same value.

ULID vs UUID vs NANOID

PropertyUUID v4ULIDNANOIDUUID v7
Size128 bits128 bitsConfigurable (default 126 bits)128 bits
Text length36 chars26 chars21 chars (default)36 chars
EncodingHex + hyphensCrockford Base32URL-safe Base64Hex + hyphens
SortableNoYes (timestamp)NoYes (timestamp)
TimestampNo48-bit msNo48-bit ms
MonotonicNoWithin same msNoWithin same ms
StandardRFC 4122Spec (community)Spec (community)RFC 9562
EcosystemUniversalGrowingJavaScript-centricGrowing

When to Choose ULID

Choose ULID when you need sortable, compact identifiers and are working in an environment where the ULID spec is well-supported. ULIDs are especially compelling for:

  • Event sourcing — Events must be ordered. ULID timestamps provide natural ordering without a separate sequence number.
  • Distributed databases — Cassandra, DynamoDB, and other distributed stores benefit from time-ordered partition keys that avoid hotspots.
  • Message queues — ULIDs as message IDs enable consumers to process messages in approximate chronological order.
  • Log aggregation — When merging logs from multiple services, ULID-based log IDs sort correctly across sources.

Choose UUID v7 instead if you need maximum ecosystem compatibility (UUID libraries exist in every language) and the 36-character format is acceptable. UUID v7 provides the same time-ordering benefit in a standardized RFC format.

Choose NANOID if you need the shortest possible identifier and sortability is not important — for example, URL shorteners or client-side generated keys where compactness matters most.

Monotonic ULIDs

When generating multiple ULIDs within the same millisecond, a naive implementation could produce IDs with identical timestamps and independent random portions — which might not sort in generation order. Monotonic ULIDs solve this by incrementing the random component by 1 for each ULID generated within the same millisecond.

This guarantees that even sub-millisecond generation preserves strict ordering. Most production ULID libraries implement monotonic generation by default.

The trade-off is that monotonic ULIDs generated in the same millisecond have a slight correlation in their random portions. In practice, this has no impact on uniqueness — the 80-bit random space is vast enough that even sequential increments within a single millisecond will never overlap across different generators.

Common Use Cases

  • Database primary keys: ULIDs provide the uniqueness of UUIDs with the index-friendly ordering of auto-increment integers
  • Event IDs in event-driven architectures: Natural chronological ordering simplifies event replay, debugging, and audit trails
  • Distributed system correlation: Independent services generate sortable IDs without coordination, enabling cross-service log correlation
  • Time-series data: The embedded timestamp allows rough time-based queries on the ID itself, without a separate timestamp column
  • API resource identifiers: 26 characters is more compact than UUID’s 36, and the case-insensitive encoding avoids URL issues

Try These Examples

Valid ULID Valid

A valid ULID — 26 characters encoded in Crockford Base32. The first 10 characters represent a 48-bit Unix timestamp in milliseconds. The remaining 16 characters are cryptographically random.

01ARZ3NDEKTSV4RRFFQ69G5FAV
Two ULIDs Generated 1 Second Apart Valid

ULIDs generated at different times are naturally sortable. The timestamp portion increments, so string sorting equals chronological sorting. No special comparator needed.

01ARZ3NDEK0000000000000000 < 01ARZ3NFHK0000000000000000