UUIDs are everywhere.
They identify users, orders, API resources, database rows, events, uploads and almost anything else that needs a unique ID without relying on a central counter.
For years, UUID v4 has been the obvious default.
Then UUID v7 arrived.
Both produce 128-bit identifiers. Both can work well in distributed systems. But they solve the problem differently — and that difference can matter once your application starts storing millions of records.
So when should you use UUID v4, and when does UUID v7 make more sense?
Let's compare them.
UUID v4 in one sentence
UUID v4 is essentially a randomly generated identifier.
A typical UUID v4 looks like this:
550e8400-e29b-41d4-a716-446655440000
The important property is that independently generated UUIDs have an extremely low probability of colliding.
That makes v4 convenient for distributed systems because multiple services can generate IDs without coordinating with one another.
You don't need:
- a central sequence
- a database round trip
- a shared counter
- knowledge of previously generated IDs
Generate one and move on.
Why UUID v4 became so popular
UUID v4 has several attractive properties.
1. It is simple
Most languages and platforms already have mature support for UUID v4.
For example, modern JavaScript can generate one with:
const id = crypto.randomUUID();
console.log(id);
There is very little to configure.
2. Generation is decentralized
Imagine several application servers creating new records at the same time.
With an auto-incrementing integer, the database usually becomes responsible for assigning the next value.
With UUIDs, each server can generate its own identifier before the record even reaches the database.
That is useful for:
- distributed systems
- offline workflows
- event generation
- message queues
- client-side object creation
- microservices
3. IDs do not reveal obvious sequence counts
Consider URLs such as:
/orders/18421
/orders/18422
/orders/18423
Someone can immediately see that the values are sequential.
A UUID looks more like:
/orders/550e8400-e29b-41d4-a716-446655440000
This makes the identifier less predictable.
But an important warning:
An unpredictable identifier is not an authorization mechanism.
Your application must still check whether the current user is allowed to access that resource.
UUIDs are identifiers, not passwords.
The downside of randomness
Randomness is also where UUID v4 can become less attractive for some databases.
Imagine a database index containing identifiers in sorted order.
Now insert these random values:
a82f...
14c9...
f931...
72ab...
09e1...
New records may belong in completely different areas of the index.
Depending on your database, storage engine, index structure and workload, highly random inserts can create more scattered writes than mostly increasing values.
This does not mean:
UUID v4 is always slow.
That would be an oversimplification.
Database behavior depends on many factors:
- database engine
- UUID storage type
- index implementation
- page size
- write volume
- caching
- hardware
- query patterns
For many applications, UUID v4 performs perfectly well.
But the desire for UUID-style decentralized identifiers that also have useful time ordering is one reason UUID v7 is interesting.
What UUID v7 changes
UUID v7 still gives you a 128-bit UUID, but part of the value represents a Unix timestamp with millisecond precision.
The remaining portion provides randomness.
Conceptually, think of it like:
TIME + RANDOMNESS
rather than:
RANDOMNESS
This gives UUID v7 an important property:
UUIDs generated at different times naturally group by generation time.
A UUID v7 might look like:
0199a4c2-96f8-7b32-a847-84e7f61a66d9
It still looks and behaves like a UUID.
But unlike v4, it contains temporal information.
Why time ordering can be useful
Suppose your application creates these records:
10:00 → record A
10:01 → record B
10:02 → record C
10:03 → record D
UUID v4 values might sort like:
d82...
19a...
f71...
52c...
There is no relationship between lexical order and creation time.
UUID v7 values generated across different milliseconds naturally group more like:
0199a...
0199b...
0199c...
0199d...
This can be useful for systems that create large numbers of records.
Potential use cases include:
- event tables
- logs
- transactions
- orders
- messages
- activity feeds
- distributed writes
Time-grouped identifiers can also behave more naturally in some indexed storage workloads.
Again, that does not guarantee that changing from v4 to v7 will magically make your database faster.
Benchmark your actual workload.
UUID v4 vs UUID v7
Here is the practical comparison.
| Feature | UUID v4 | UUID v7 |
|---|---|---|
| Main input | Randomness | Timestamp + randomness |
| Decentralized generation | Yes | Yes |
| Natural time grouping | No | Yes |
| Creation time embedded | No | Approximate time |
| Easy library support | Excellent | Increasing rapidly |
| Good for generic IDs | Yes | Yes |
| Useful for time-heavy workloads | Possible | Often attractive |
| Predictable sequence | No | Time component is observable |
Neither is universally better.
They optimize for slightly different priorities.
One subtle limitation: the same millisecond
It is tempting to describe UUID v7 as:
perfectly ordered by creation time
That is not quite correct.
UUID v7 includes a millisecond timestamp.
If several UUIDs are generated during the same millisecond, the timestamp portion can be identical.
Unless the implementation adds a monotonic strategy, their relative ordering inside that millisecond is not guaranteed to represent exact creation order.
So a safer description is:
UUID v7 provides time grouping across milliseconds.
If strict ordering matters, use an explicit timestamp or sequence designed for that requirement.
UUID v7 exposes time information
There is another tradeoff.
UUID v4 does not encode its creation timestamp.
UUID v7 does.
That means someone inspecting a UUID v7 can derive an approximate generation time from it.
For most application IDs, that may be completely acceptable.
But it matters if hiding creation time is part of your threat model.
For example, you may not want publicly exposed identifiers to reveal when a sensitive resource was created.
Again:
Choose an identifier based on your requirements, not because one version is newer.
What about database primary keys?
This is where the debate becomes interesting.
For a new application, you might be choosing between:
BIGINT auto increment
UUID v4
UUID v7
Each has advantages.
Auto-incrementing integers
Advantages:
- compact
- naturally ordered
- excellent database support
- easy to debug
Tradeoffs:
- usually database-generated
- require coordination
- expose simple sequence information when public
UUID v4
Advantages:
- decentralized
- mature
- unpredictable
- easy to generate almost anywhere
Tradeoffs:
- random index distribution
- no time information
- larger than common integer IDs
UUID v7
Advantages:
- decentralized
- time-grouped
- UUID-compatible
- often friendlier to ordered workloads
Tradeoffs:
- exposes approximate creation time
- newer ecosystem support
- not strictly ordered within every millisecond
There is no universal winner.
Store UUIDs properly
Another performance mistake has nothing to do with the UUID version.
It is how the UUID is stored.
A UUID is 128 bits.
Its human-readable representation contains 36 characters:
550e8400-e29b-41d4-a716-446655440000
But storing every UUID as a generic text field is not always necessary.
Many databases provide dedicated UUID types.
For example, PostgreSQL supports:
CREATE TABLE users (
id UUID PRIMARY KEY
);
Using the database's native UUID type can provide clearer semantics and more efficient storage than treating identifiers as arbitrary strings.
Always check what your database supports.
When I would choose UUID v4
UUID v4 remains a good choice when:
- you want maximum ecosystem compatibility
- random identifiers are desirable
- your current system already uses v4
- write ordering is not a concern
- you do not want the ID to encode creation time
- your database workload already performs well
There is little reason to migrate a working application from v4 solely because v7 exists.
When I would choose UUID v7
For a new application, I would seriously consider UUID v7 when:
- records are frequently inserted
- time grouping is useful
- IDs are stored in indexed database columns
- multiple services generate identifiers
- you want sortable UUID-style identifiers
- exposing approximate creation time is acceptable
This is particularly interesting for systems dealing with large chronological datasets.
Think:
events
messages
orders
logs
audit records
transactions
Don't use UUIDs as secrets
This deserves repeating.
Neither UUID v4 nor UUID v7 should replace proper secrets.
Do not treat a UUID as equivalent to:
- an API key
- session token
- password-reset token
- authentication token
- authorization rule
Even when an identifier is difficult to guess, your application should still enforce access control.
Use cryptographically appropriate tokens for security-sensitive purposes.
Try both versions
Sometimes the easiest way to understand the difference is simply to generate both.
You can compare UUID v4 and v7 using the Genory UUID Generator.
Generate several v4 values and notice how unrelated they appear.
Then generate several v7 values and compare identifiers created at different times.
Genory also exposes UUID generation through its developer API. For supported API access, the current documentation is available at genory.dev/docs.
Conceptually, the API supports choosing the UUID version:
version = v4
or:
version = v7
That makes it easy to test how both identifier strategies behave in your own fixtures before making an architectural decision.
So which one should you use in 2026?
For an existing system successfully using UUID v4:
Keep using v4 unless you have a concrete reason to change.
For a new application where UUIDs will become heavily indexed database keys:
UUID v7 deserves serious consideration.
For identifiers where you do not want to reveal approximate creation time:
UUID v4 may be preferable.
For systems where chronological grouping is useful:
UUID v7 is often the more interesting choice.
The most important rule is not:
Always use the newest UUID version.
It is:
Understand what information your identifier contains and how your storage system will use it.
Final thought
UUID v4 solved an important distributed-systems problem extremely well.
UUID v7 does not replace it.
Instead, v7 adds something many modern applications can benefit from: time-aware ordering without giving up decentralized UUID generation.
That makes the decision surprisingly simple:
Use v4 when randomness is exactly what you need.
Use v7 when time grouping gives your system an advantage.
And if performance is the reason you're choosing between them, benchmark your own database instead of trusting a rule of thumb.
Top comments (0)