UUID vs ULID: Which ID Format to Use?
Every application needs unique identifiers. The question is which format: UUID v4, UUID v7, ULID, or something else? Each has trade-offs in sortability, collision probability, database performance, and information leakage.
This guide compares the three most popular options so you can make an informed choice.
UUID v4: The Default Choice
UUID v4 (Universally Unique Identifier, version 4) generates 122 random bits in the standard 8-4-4-4-12 hex format:
550e8400-e29b-41d4-a716-446655440000
Advantages:
- Universally supported — every language, database, and framework has UUID v4 support
- No coordination needed — two systems can generate UUIDs independently with negligible collision probability (2^122 possibilities)
- No information leakage — purely random, reveals nothing about creation time or order
Disadvantages:
- Not sortable by time — random distribution causes B-tree index fragmentation in databases, leading to slower inserts and more page splits
- Not human-readable — 36 characters of hex with dashes
- No embedded timestamp — you cannot determine when a record was created from its ID
UUID v7: Sortable UUIDs
UUID v7 (defined in RFC 9562) embeds a millisecond-precision Unix timestamp in the first 48 bits, followed by random bits:
018f3e5c-5b00-7000-8000-1a2b3c4d5e6f
│ │
└── timestamp ───────┘ random ──────┘
Advantages:
- Time-sortable — UUIDs created later have higher values, matching insertion order
- Database-friendly — sequential values reduce B-tree page splits and improve write performance
- Standard format — uses the same 8-4-4-4-12 format as UUID v4, so existing UUID columns work without schema changes
- Timestamp extractable — you can recover the creation time from the ID
Disadvantages:
- Information leakage — the creation timestamp is readable by anyone who has the ID
- Millisecond resolution — multiple IDs generated in the same millisecond are ordered by random bits, not guaranteed monotonic within that millisecond
- Newer standard — some older libraries and databases do not yet have native UUID v7 support
ULID: Compact and Sortable
ULID (Universally Unique Lexicographically Sortable Identifier) uses a different format: a 48-bit millisecond timestamp followed by 80 random bits, encoded as 26 Crockford Base32 characters:
01ARZ3NDEKTSV4RRFFQ69G5FAV
│ │
└ timestamp┘ randomness ────┘
Advantages:
- Shorter — 26 characters vs 36 for UUID
- Case-insensitive — Crockford Base32 uses only uppercase letters and digits, no confusable characters (no I/L/O/U)
- Time-sortable — lexicographic sort matches chronological order
- Monotonic option — within the same millisecond, the random component can be incremented to guarantee ordering
Disadvantages:
- Not a standard format — ULIDs cannot be stored in UUID database columns without conversion
- Less ecosystem support — not natively supported by most databases and ORMs
- Timestamp leakage — same as UUID v7
Head-to-Head Comparison
| Feature | UUID v4 | UUID v7 | ULID |
|---|---|---|---|
| Length | 36 chars | 36 chars | 26 chars |
| Format | Hex + dashes | Hex + dashes | Crockford Base32 |
| Sortable by time | No | Yes | Yes |
| Timestamp embedded | No | Yes (ms) | Yes (ms) |
| Random bits | 122 | 62 | 80 |
| Database column type | UUID | UUID | Text or UUID (with conversion) |
| Standard | RFC 9562 | RFC 9562 | Informal spec |
| Privacy (no time leak) | Yes | No | No |
Database Performance Impact
In databases with B-tree indexes (PostgreSQL, MySQL, SQLite), random UUIDs (v4) cause index fragmentation because new values are inserted at random positions in the tree. This leads to:
- More page splits during inserts
- Lower cache hit ratio (pages are not sequential)
- 2-5x slower bulk inserts compared to sequential IDs
UUID v7 and ULID solve this because their time-based prefix makes new values approximately sequential, appending to the end of the index rather than inserting in the middle.
Benchmarks (PostgreSQL, 10M rows):
- Auto-increment integer: baseline
- UUID v7: ~1.2x slower inserts, ~1.1x slower reads
- UUID v4: ~2.5x slower inserts, ~1.3x slower reads
When to Use Each
UUID v4 — when you need maximum privacy (no timestamp leakage), universal compatibility, or are working with systems that only support UUID format. Good for user-facing IDs where you do not want to reveal creation order.
UUID v7 — when you need time-sorted IDs in a system that already uses UUID columns. The best choice for new projects using PostgreSQL, MySQL, or any database with native UUID support. Drop-in replacement for UUID v4 with better performance.
ULID — when you need shorter IDs, case-insensitive identifiers, or are building a system without UUID column constraints. Good for URLs, API keys, and systems where 26 characters is significantly better than 36.
Generate IDs
StackCache UUID & ULID Generator creates UUID v4, UUID v7, and ULID identifiers with cryptographic randomness, directly in your browser. Generate single IDs or batches of up to 100 — all locally with no server.
Try it yourself
Open the tool mentioned in this guide — it runs locally in your browser, no account needed.
Open tool