For years
a UUID meant version 4.
One hundred and twenty two random bits,
and a few fixed ones
saying what kind it was.
So code grew up
around that randomness,
without saying so.
Shard by the first two characters.
Spread evenly,
because the characters are random.
Put the id in a public link.
Nobody can tell anything from it,
because it is random.
Those were never promises.
They were properties of one version.
In May 2024
RFC 9562 replaced the old UUID standard
and added version 7.
A version 7 UUID
starts with forty eight bits
of Unix time in milliseconds.
The randomness comes after.
That is the point of it.
Ids made one after another
sort one after another,
so new rows go to the end
of a database index
instead of landing all over it.
Fewer page splits.
Better cache use.
Faster inserts.
It is a good change,
and it is spreading.
PostgreSQL 18
ships a uuidv7 function.
Libraries in most languages
generate them already.
Some will make it the default.
Now read your old assumptions again.
Shard by the first characters,
and every new row
goes to the same shard,
because every new id
starts with almost the same time.
Your even spread
becomes one hot bucket.
Put the id in a link,
and anyone holding it
can read the creation time
to the millisecond.
When an account was opened.
When an order was placed.
How many came before it, roughly,
if they collect a few.
And treating an id as a secret
was always wrong.
The RFC says plainly
not to use UUIDs
as security capabilities.
Version 7 just makes it easier to see.
So find the places
that depend on what an id looks like.
Hash the id
before you choose a shard.
Use a separate random token
for any link that must not be guessed.
Decide, on purpose,
whether a creation time
is something your users
should be able to read off a URL.
An id should identify.
The day it starts carrying meaning,
somebody will read it.
– Serguey Asael Shinder
Top comments (0)