ULID vs UUID – Choosing the Right Sortable ID Format
Generate UUID v4 or v7 — the modern standard for sortable unique IDs
No signup • Runs in browser • Free
Random UUID v4 primary keys fragment database indexes. ULID (Universally Unique Lexicographically Sortable Identifier) was one of the first widely adopted solutions — a 128-bit ID with a 48-bit timestamp prefix and Crockford Base32 encoding that makes IDs sort chronologically and stay URL-safe without hyphens. Then UUID v7 arrived in RFC 9562 (2024) and solved the same problem using the established UUID format. Now the question is not "UUID or ULID" but "which time-ordered format should I standardize on, and why?"
The short answer for most new projects: UUID v7. It is standardized, broadly supported in databases and ORMs, and backward-compatible with existing UUID columns. ULID remains relevant in contexts where its compact, hyphen-free representation or Crockford Base32 alphabet provides a specific advantage. Understanding the tradeoffs prevents picking a format based on what you read first.
# The three formats side by side:
UUID v4 (random): f47ac10b-58cc-4372-a567-0e02b2c3d479
← 36 chars with hyphens, 32 hex chars without
← purely random, no ordering
UUID v7 (time-ordered): 018d4e7c-a234-7f12-9abc-0a1b2c3d4e5f
← same format as v4, sorts chronologically
← 48-bit ms timestamp + random suffix
ULID (time-ordered): 01HQ4K8J3PPNWHE0FYXQR3YQZS
← 26 chars, no hyphens, Crockford Base32
← 48-bit ms timestamp + 80-bit random
← lexicographically sortable as a string
Quick summary
- ✓ULID uses Crockford Base32 encoding — 26 characters, no hyphens, case-insensitive, URL-safe.
- ✓UUID v7 uses standard UUID format — compatible with existing UUID columns, ORMs, and database tooling.
- ✓Both encode a 48-bit millisecond timestamp prefix — both sort chronologically.
- ✓DevToolBox tools run entirely in your browser — no signup.
Format Comparison
ULID and UUID v7 solve the same core problem — sortable unique IDs without a central sequence generator — but make different tradeoffs in encoding, size, and compatibility.
| Property | UUID v4 | UUID v7 | ULID | |---|---|---|---| | Sortable | No | Yes | Yes | | Timestamp precision | None | Millisecond | Millisecond | | String length | 36 (with hyphens) | 36 (with hyphens) | 26 | | Encoding | Hex | Hex | Crockford Base32 | | Hyphens | Yes | Yes | No | | Case sensitive | No | No | No (Crockford) | | Standard | RFC 4122 | RFC 9562 | Spec at github.com/ulid | | DB native type | UUID (PG), BINARY(16) | UUID (PG), BINARY(16) | CHAR(26) or BINARY(16) |
The ULID spec encodes 128 bits as 26 Crockford Base32 characters. The Crockford alphabet removes visually ambiguous characters (I, L, O, U) — 01HQ4K8J3P is unambiguous regardless of font. UUID v7 uses the same hex encoding and hyphen structure as all other UUIDs, which means it works directly in any database column or application code that already handles UUIDs.
Database and ORM Compatibility
UUID v7 has a significant practical advantage: it is a UUID. Any database that supports UUID storage — PostgreSQL's native uuid type, MySQL's BINARY(16), SQLite's TEXT(36) — handles v7 identically to v4. ORMs that support UUID primary keys (Prisma, Hibernate, SQLAlchemy, ActiveRecord) work with v7 without configuration changes.
ULID requires more deliberate setup. The common storage options are:
CHAR(26)— stores the 26-character Crockford string directly. Sortable as a string, human-readable, but 26 bytes vs 16 for binary storage.BINARY(16)— stores the 128-bit value compactly. Same size as a UUID but requires the application to handle encoding and decoding explicitly.ULIDextension — PostgreSQL has third-party extensions (pg_ulid) that add native ULID support, but they are not part of the standard distribution.
For projects that already use UUIDs, migrating to ULID introduces a format change that affects API contracts, URL structures, and database schemas. Migrating from UUID v4 to UUID v7 is transparent — the format is identical, only the generation strategy changes.
When ULID Is the Better Choice
ULID wins in specific contexts where its encoding properties are directly useful.
- Short, human-readable IDs in URLs.
01HQ4K8J3PPNWHE0FYXQR3YQZSis 26 characters without hyphens — shorter and URL-safe without percent-encoding. For IDs that appear in user-visible URLs where brevity matters, ULID is more compact than a UUID with hyphens. - Log-friendly IDs. The Crockford alphabet avoids characters that are ambiguous in fixed-width fonts and log output. For IDs that appear frequently in logs and are read by humans, ULID's character set reduces reading errors.
- Lexicographic sort without UUID parsing. ULID strings sort correctly in any system that does lexicographic string comparison — no UUID-aware comparison function needed. This matters in systems like DynamoDB that sort range keys lexicographically.
- Existing ULID codebases. If your codebase already uses ULID consistently, changing to UUID v7 introduces dual-format complexity without meaningful benefit. Stay consistent.
When UUID v7 Is the Better Choice
UUID v7 wins in most contexts because it is a drop-in replacement for UUID v4 with better database performance.
- New projects starting from scratch. Choose UUID v7 as your primary key format from the start. It is standardized (RFC 9562), has broad library support, and works with all existing UUID infrastructure.
- Existing UUID codebases. If your schema uses UUID columns, UUID v7 is a zero-configuration upgrade — no schema changes, no ORM changes, just switch the generation function.
- PostgreSQL and databases with native UUID types. Native UUID types store 16 bytes regardless of v4 or v7. The sort-order improvement comes for free with no storage overhead.
- API-first designs. UUID v7 appears identical to v4 in API responses — the same 36-character hyphenated format that developers expect. ULID requires client code to handle a different format. See our guide on UUID v4 vs v7 for the performance details.
Frequently Asked Questions
Is ULID dead now that UUID v7 exists?
Not dead, but UUID v7 has reduced the use cases where ULID is the clear winner. ULID still has advantages in its compact encoding, Crockford alphabet, and existing adoption in certain ecosystems (Rust, Elixir, some Node.js projects). For new projects with no existing ID format commitment, UUID v7 is the pragmatic choice due to its standardization and compatibility.
Can ULID and UUID v7 coexist in the same system?
Technically yes, but it is not recommended. Mixed ID formats in the same system create confusion — which format does a given endpoint return? Which format should a given column store? Pick one and use it consistently across the application.
What about NanoID?
NanoID is a different format entirely — it generates short, URL-safe random strings of configurable length using a custom alphabet. It has no embedded timestamp and is not sortable. NanoID trades uniqueness guarantees (based on length and alphabet) for compactness. Use it for short codes, share links, and identifiers where length matters more than strict uniqueness or sortability. Do not use it as a database primary key at scale.
Conclusion
ULID and UUID v7 solve the same problem with different tradeoffs. UUID v7 wins on compatibility and standardization; ULID wins on compact encoding and Crockford alphabet readability. For most new projects, UUID v7 is the pragmatic default — it drops into existing UUID infrastructure and provides the sortability benefits of ULID without the format change. ULID remains the better choice in contexts where its specific encoding properties are directly valuable.
If you need to generate UUID v4 or v7 IDs instantly, the DevToolBox UUID Generator produces both. DevToolBox tools run entirely in your browser — no signup, no install, nothing sent to a server.
Generate UUID v4 or v7 in seconds
Choose v4 for random opacity or v7 for time-ordered sortability. Cryptographically secure, free, no signup, browser-only.
Generate UUID Now →