UUIDv7 is the first UUID that databases actually wanted
Why this topic matters #
One of the big reasons UUIDs became popular is simple: your app can generate IDs locally, without waiting for the database or another central service to assign them.
That was great for distributed systems, background jobs, offline clients, and microservices.
But there was always a catch.
The most common UUID many teams used was UUIDv4, which is basically random. That randomness is good for uniqueness, but not so good for database indexes. When your primary key is random, inserts land all over the index instead of mostly at the end. That means more page splits, worse locality, and usually less friendly write patterns.
UUIDv7 matters because it keeps the “generate IDs anywhere” model, but now the values are ordered by time. In simple terms: it gives UUIDs a timeline.
That is why this version is important, and it is also why databases are paying
attention to it. PostgreSQL 18, released on September 25, 2025, added native
UUIDv7 generation with uuidv7().
First, what is UUIDv7? #
UUIDv7 is a 128-bit identifier format defined in RFC 9562.
The short version is this:
- the beginning of the UUID stores a Unix timestamp in milliseconds
- the rest stores version bits, variant bits, and randomness
- because the timestamp is at the front, the UUID becomes sortable by creation time
That is the big change.
Older UUID versions solved different problems:
- UUIDv1 had time ordering, but it exposed machine and timing details many teams did not want to leak
- UUIDv4 became popular because it is simple and random, but it has no natural ordering
UUIDv7 is basically the practical middle ground. It is modern, timestamp-first, and still keeps enough randomness to work well in distributed systems.
How it works in simple terms #
The mental model is:
- Take the current Unix time in milliseconds.
- Put that timestamp in the most significant bits.
- Fill the rest with randomness, plus the required UUID version and variant bits.
Because the timestamp goes first, lexicographic order and creation order are roughly aligned.
That does not mean UUIDv7 is an auto-increment integer.
It is better to think of it as a time-ordered UUID, not a strict sequence. Two IDs created in the same millisecond are still differentiated by the remaining bits. Some implementations also use part of those bits to improve ordering inside the same millisecond.
Why this is such a big improvement #
This fixes a very real database problem.
With UUIDv4, inserts are randomly distributed across a B-tree index. With UUIDv7, new values are much more likely to be inserted near the end because the newest timestamps sort after older ones.
Why should you care?
- write-heavy tables usually get friendlier index behavior
- range queries by ID become more meaningful
- pagination and “latest records first” patterns become easier to reason about
- you still avoid central ID coordination across services
This is the part previous popular UUID choices were missing. We had globally unique IDs, but not IDs that cooperated nicely with storage engines.
Why UUIDv7 fits distributed systems so well #
Distributed systems need identifiers that do not depend on a single database sequence.
If multiple services, workers, mobile clients, or regions can create records, you want them to generate IDs independently. That part was already true for UUIDs in general.
What UUIDv7 adds is a much better operational story:
- IDs can be created outside the database
- they remain globally unique with extremely high probability
- they preserve a time-based order that is useful for storage and debugging
That last point is more important than it looks.
When you inspect logs, events, or records across systems, a UUIDv7 often gives
you a rough sense of “when” just from the ID ordering. It is not a replacement
for created_at, but it is a much more human-friendly ID than UUIDv4.
Going a bit deeper: what ordering really means #
This part is important because UUIDv7 is often oversold.
UUIDv7 gives you temporal ordering, not a perfect global sequence.
That means:
- IDs generated later will usually sort after IDs generated earlier
- IDs created in the same millisecond may still be ordered by extra randomness or implementation-specific monotonic bits
- clock skew between machines can still affect ordering
So if your requirement is “every new row must have an exact gapless sequence”, UUIDv7 is not your tool.
But if your requirement is “I want decentralized IDs that behave much better in indexes and still roughly follow creation time”, UUIDv7 is a very strong option.
A small example #
Imagine these three IDs were generated in this order:
019575cf-4d12-7db3-a4f2-8c1d5f8b19aa
019575cf-4d13-74e8-b0ec-2bc2e1f0dd31
019575cf-4d14-7a40-8df2-f3c8d7a4a921
You do not need to decode every bit to notice something useful: the values tend to move forward with time.
That is very different from UUIDv4, where the next generated value is effectively unrelated to the previous one from an ordering perspective.
PostgreSQL 18 is a good sign #
PostgreSQL 18 added native UUIDv7 generation through uuidv7().
That matters for two reasons.
First, it means UUIDv7 is no longer just an app-layer trick that you implement with a library in every language. A major database now understands it directly.
Second, it shows where the ecosystem is moving: toward UUIDs that are still decentralized, but much more database-friendly than UUIDv4.
In PostgreSQL 18 you can do this:
create table orders (
id uuid primary key default uuidv7(),
customer_id uuid not null,
total_amount numeric(10,2) not null,
created_at timestamptz not null default now()
);
You can also extract the embedded timestamp:
select uuid_extract_timestamp(uuidv7());
That does not mean PostgreSQL stores rows magically in perfect order forever, but it does mean the primary key values are far more aligned with insertion time than random UUIDs.
Can this replace incremental IDs? #
Sometimes yes, sometimes no.
If by “incremental IDs” you mean “IDs that move forward over time and behave nicely in indexes”, then UUIDv7 is a serious replacement.
If by “incremental IDs” you mean:
- tiny integers
- gapless sequences
- easy human-readable references
then no, a classic integer sequence still wins.
This is the trade-off:
- integer IDs are smaller and simpler
- UUIDv7 is better when ID generation must happen across nodes, services, or offline clients without coordination
In many real systems, that trade is worth it.
When I would use it #
I would seriously consider UUIDv7 when:
- the system is distributed or will become distributed
- IDs are generated in multiple services or outside the database
- the table is large enough that random-key index behavior starts to hurt
- I want the safety of UUIDs without the storage penalties of pure randomness
When I would not use it #
I would avoid UUIDv7 when:
- the system is small and a plain
bigserialis enough - humans frequently read or type the identifiers
- strict sequential numbering is a business requirement
- storage size is extremely sensitive and 128-bit keys are not justified
For small monoliths, a regular integer key is still a very good option. Not every project needs distributed-ID machinery.
Links #
- RFC 9562 UUID specification: https://www.rfc-editor.org/rfc/rfc9562
- PostgreSQL 18 UUID type docs: https://www.postgresql.org/docs/18/datatype-uuid.html
- PostgreSQL 18 UUID functions: https://www.postgresql.org/docs/18/functions-uuid.html
- PostgreSQL 18 release notes: https://www.postgresql.org/docs/18/release-18.html
- PostgreSQL 18 release announcement: https://www.postgresql.org/about/news/postgresql-18-released-3142/
Conclusions #
UUIDv7 is important because it fixes the part of UUIDs that databases never really liked: random ordering.
It does not try to become a perfect sequence, and that is fine. What it offers is more practical: globally unique IDs, local generation, better index behavior, and a time-based order that works much better in modern systems.
That is why PostgreSQL 18 adding uuidv7() matters. It is not just one more
function. It is a sign that time-ordered UUIDs are moving from “nice idea” to
“normal tool you can rely on”.