UUID vs ULID: Which Unique ID Format to Use

Compare UUID and ULID for database primary keys and distributed IDs. Understand sortability, encoding, size, and compatibility trade-offs before choosing an ID format.

UUID vs ULID Comparison

ULID (Universally Unique Lexicographically Sortable Identifier) was designed to solve UUID's key weakness for databases: random insertion order. Here's how they compare.

  • UUID v4: 550e8400-e29b-41d4-a716-446655440000 โ€” 36 chars with hyphens, random, not sortable
  • ULID: 01ARZ3NDEKTSV4RRFFQ69G5FAV โ€” 26 chars, Crockford Base32, time-ordered
  • UUID v7: 018e1e6e-4b4c-7c3a-9c2b-3f4a5b6c7d8e โ€” standard UUID format with embedded timestamp

Key Differences

  • Sortability: ULID is lexicographically sortable (first 10 chars encode millisecond timestamp) โ€” UUID v4 is not; UUID v7 is
  • String length: ULID is 26 characters vs UUID's 36 (with hyphens) or 32 (without) โ€” 28% shorter
  • Character set: ULID uses Crockford Base32 (no ambiguous chars like O/0, I/l) โ€” URL-safe and human-readable; UUID uses lowercase hex
  • Database storage: Both fit in a CHAR(36) or binary(16) column; ULID fits in CHAR(26) โ€” minor storage advantage
  • Standard support: UUID is an IETF/ISO standard (RFC 4122) with native support in most databases; ULID is a community spec with no native DB type
  • Monotonicity: Multiple ULIDs generated in the same millisecond increment the random portion to maintain sort order โ€” UUID v7 handles this similarly

When to Choose Each

  • Choose UUID v4 when using a database or ORM with built-in UUID support (PostgreSQL uuid type, MySQL UUID(), Rails SecureRandom.uuid) and sort order doesn't matter
  • Choose ULID when you want time-sortable IDs in a system where UUID isn't natively supported and you control the full stack
  • Choose UUID v7 when you want time-ordering in UUID format โ€” the new RFC 9562 standard, increasingly supported in databases and libraries
  • Avoid ULID if your database or ORM expects standard UUID format โ€” you'll lose native type support and have to store as a string

Frequently Asked Questions

Is ULID better than UUID for database primary keys?

ULID and UUID v7 both solve the index fragmentation problem of UUID v4 by being time-ordered, leading to sequential inserts in B-tree indexes. ULID has a slight size advantage (26 vs 36 chars as string) but lacks native database type support. UUID v7 achieves the same performance benefit while staying in the standard UUID format. For new projects, UUID v7 is the cleaner choice if your database/library supports it; ULID is a solid alternative if UUID v7 support isn't available.

Can I migrate from UUID to ULID?

Migrating existing UUIDs to ULIDs requires a schema migration and application-layer changes. It's non-trivial if the IDs are embedded in URLs, shared with external systems, or stored as foreign keys across many tables. For existing UUID-based systems, UUID v7 is a less disruptive path to time-ordered IDs โ€” it fits in the same column type and doesn't require changing your ID format externally.