· articles · 4 min read
By Ankit JainULID vs UUID v7
A deep technical comparison of UUID and ULID from a system design perspective. Covers structure, entropy, ordering guarantees, database behavior, indexing impact, distributed generation, and cryptographic considerations.
ULID vs UUID: A System-Level Comparison
When you design distributed systems, identifiers quietly shape performance, data layout, replication behavior, and even failure modes. UUIDs have been the default choice for decades, but ULIDs were introduced to solve specific operational issues that UUIDs do not address well.
This article compares ULID and UUID from a system architect’s viewpoint. The focus is not syntax or libraries, but how these identifiers behave under load, across nodes, inside databases, and over time.
High-Level Overview
- UUID (Universally Unique Identifier) is defined by RFC 4122 and comes in multiple versions. UUID v4 is the most common in modern systems and is fully random. Other versions embed timestamps or node identifiers.
- ULID (Universally Unique Lexicographically Sortable Identifier) is a newer format that combines a millisecond timestamp with randomness, encoded using Crockford’s Base32. The design goal is simple: preserve global uniqueness while making identifiers sortable by creation time.
Structural Characteristics
| Property | ULID | UUID v4 or v7 |
|---|---|---|
| Length | 26 characters | 36 characters |
| Encoding | Base32 (no I, L, O, U) | Hexadecimal |
| Bit layout | 48-bit timestamp + 80-bit randomness | Version dependent |
| Case sensitivity | Uppercase only | Case insensitive |
| Human readability | Moderate | Low |
Why structure matters
ULID explicitly optimizes for ordered insertion, while UUIDv4 optimizes for entropy. From a system perspective, structure affects more than aesthetics:
- Encoding impacts index size and cache density.
- Timestamp placement affects write amplification in B-trees.
- Randomness placement affects hot-spotting under concurrent writes.
If you aren’t familiar with ULID, check out this article.
Uniqueness in Space vs Uniqueness in Time
Architecturally, uniqueness has two orthogonal dimensions.
Unique in Space
An identifier is unique in space if two independent nodes can generate IDs without coordination and still avoid collisions.
- UUIDv4 achieves this via 122 bits of randomness.
- ULID achieves this via 80 bits of randomness per millisecond.
Both are effectively collision-free at realistic scale. Even at millions of IDs per second, collision probability remains negligible.
Unique in Time
An identifier is unique in time if its ordering reflects creation time.
- UUIDv4 has no ordering guarantee.
- ULID guarantees lexicographic ordering by timestamp, assuming monotonic clocks.
- UUIDv1 and UUIDv7 embed time, but with different tradeoffs.
For event logs, append-only storage, and time-series data, time ordering is not optional. It directly affects query plans and compaction behavior.
Database and Storage Implications
Index locality
Random identifiers cause scattered inserts in B-tree indexes.
- UUIDv4 inserts are uniformly distributed.
- This leads to page splits, cache churn, and lower write throughput.
- The effect becomes visible under sustained write load.
ULIDs insert sequentially by timestamp.
- New rows cluster near the end of the index.
- Page splits are minimized.
- Write amplification drops significantly in high-ingest systems.
This difference alone is often enough to justify ULID for write-heavy tables.
Storage footprint
- ULID: 26 characters.
- UUID: 36 characters.
At small scale this difference is irrelevant. At hundreds of millions of rows, it directly affects index size, cache residency, and backup volume.
Binary storage narrows the gap, but textual identifiers still dominate logs, APIs, and message payloads.
Generation Cost and Throughput
Both ULID and UUID generation is cheap relative to network or disk IO.
- UUIDv4 generation relies on cryptographically secure randomness.
- ULID generation requires a timestamp read plus randomness.
In practice:
- Both generate millions of IDs per second per core.
- The difference is not CPU-bound.
- The operational impact comes from downstream effects like sorting and indexing.
Generation speed should not be your primary decision factor.
UUID v7: Bridging the Gap
UUID v7 was introduced to combine UUID compatibility with time ordering.
Key properties:
- Timestamp-based ordering.
- Random bits for collision resistance.
- Same 128-bit size as other UUIDs.
- String length remains 36 characters.
UUID v7 narrows the gap between UUIDv4 and ULID, but does not eliminate tradeoffs.
ULID vs UUID v7
| Property | ULID | UUID v7 |
|---|---|---|
| Sortable | Yes | Yes |
| Timestamp precision | Milliseconds | Milliseconds |
| Randomness | 80 bits | High |
| String length | 26 | 36 |
| Encoding | Base32 | Hexadecimal |
| Human readability | Higher | Lower |
| Index locality | Strong | Strong |
From a system design perspective, both solve the same core problem. ULID favors compactness and readability. UUID v7 favors ecosystem continuity.
Cryptographic and Security Considerations
UUIDv4
- High entropy.
- Unpredictable.
- Suitable for public identifiers, tokens, and references where guessing must be infeasible.
ULID
- Timestamp reveals creation time.
- Partial predictability.
- Not suitable for security-sensitive identifiers.
If identifiers are exposed externally and carry security implications, UUIDv4 is the safer default.
Final Take
Identifiers are not interchangeable primitives. They influence database performance, replication behavior, and long-term operability.
As an architect, the right choice depends on where the ID flows and how long the system will live with that decision.
- UUIDs prioritize entropy and standardization.
- ULIDs prioritize ordering and operational efficiency.
UUID v7 attempts to balance both.