Ask HN: We just had an actual UUID v4 collision...
75 points
8 hours ago
| 24 comments
| HN
I know what you're thinking... and I still can't believe it, but...

This morning, our database flagged a duplicate UUID (v4). I checked, thinking it may have been a double-insert bug or something, but no.

The original UUID was from a record added in 2025 (about a year ago), and today the system inserted a new document with a fresh UUIDv4 and it came up with the exact same one:

b6133fd6-70fe-4fe3-bed6-8ca8fc9386cd

We're using this: https://www.npmjs.com/package/uuid

I thought this is technically impossible, and it will never happen, and since we're not modifying the UUIDs in any way, I really wonder how that.... is possible!? We're literally only calling:

import { v4 as uuidv4 } from "uuid";

const document_id = uuidv4();

... and then insert into the database, that's it.

Additionally, the database only has about 15.000 records, and now one collision. Statistically... impossible.

Has that ever happened to anyone?! What in the...

jandrewrogers
4 minutes ago
[-]
This is surprisingly common.

The security of UUIDv4 is based on the assumption of a high-quality entropy source. This assumption is invalidated by hardware defects, normal software bugs, and developers not understanding what "high-quality entropy" actually means and that it is required for UUIDv4 to work as advertised.

It is relatively expensive to detect when an entropy source is broken, so almost no one ever does. They find out when a collision happens, like you just did.

UUIDv4 is explicitly forbidden for a lot of high-assurance and high-reliability software systems for this reason.

reply
throwaway_19sz
6 hours ago
[-]
Funny story no one will believe, but it’s true. A good friend of mine joined a startup as CTO 10 years ago, high growth phase, maybe 200 devs… In his first week he discovered the company had a microservice for generating new UUIDs. One endpoint with its own dedicated team of 3 engineers …including a database guy (the plot thickens). Other teams were instructed to call this service every time they needed a new ‘safe’ UUID. My pal asked wtf. It turned out this service had its own DB to store every previously issued UUID. Requests were handled as follows: it would generate a UUID, then ‘validate’ it by checking its own database to ensure the newly generated UUID didn’t match any previously generated UUIDs, then insert it, then return it to the client. Peace of mind I guess. The team had its own kanban board and sprints.
reply
wongarsu
4 hours ago
[-]
At some point someone optimizes the system to a global company-wide incrementing 128 bit counter. Instead of needing a costly database lookup against a growing database the microservice just fetches the current counter, increments it by one and hands out the new value. Easy, fast O(1) operation.

This even allows you to shard the service to provide high availability and distribute the service globally to reduce latency. Just give each instance a dedicated id range it can hand out. I'd suggest reserving some of the high bits to indicate data center id, and a couple more bits for id-generator instance within that dc.

Wait a second, this starts to look familiar ... does Twitter still do that, or did they eventually switch?

reply
sheept
1 minute ago
[-]
Twitter snowflakes haven't changed. Most of the bits go to the timestamp, which I guess is a global incrementing counter as you described
reply
throw0101c
2 minutes ago
[-]
> At some point someone optimizes the system to a global company-wide incrementing 128 bit counter.

Some UUID versions include time, so there's a bit of a counter in that.

reply
roryirvine
3 hours ago
[-]
I've seen similar, buried deep within a major SV tech co.

Their process was a bit more complex because the master list of in-use UUIDs was stored in an external CMDB service run by a different department. They got a daily dump of that db, so were able to check that when generating a "provisional" id. Only once it had been properly submitted to the CMDB did it became "confirmed".

They had guardrails in place to prevent "provisional" ids being used in production, and a process for recycling unused "confirmed" ids. Oh, and they did regular audits which were taken very seriously by management.

Last I heard, they were 18 months into a 6 month project to move their local database cache to Zookeeper...

reply
franktankbank
5 hours ago
[-]
Who has the balls to form that team? Were they disbanded?
reply
ryandvm
3 hours ago
[-]
Pffft - they didn't need to store the whole UUID, just a hash. Dummies.
reply
dd8601fn
3 hours ago
[-]
They thought of that, but they were still working on hiring a team to maintain the hashing microservice.
reply
mstaoru
1 hour ago
[-]
Hashing microservice deployment was blocked by random generator microservice stuck in Pending because it needed an UUID from UUID microservice which was blocked by hashing.
reply
mrsvanwinkle
1 hour ago
[-]
already laughing from parent comment this is well done
reply
jbverschoor
8 minutes ago
[-]
Most plausible cause: uuid package depends on some random number generator package, which has recently been compromised in order to make “random” numbers predictable. As a result, many crypto (ssl + currency) projects are compromised due to a supplychain attack.
reply
juancn
2 hours ago
[-]
Something off on how the RNG is initialized? Lack of entropy?

If the rng is not customized it will use:

    const rnds8 = new Uint8Array(16);
    export default function rng() {
        return crypto.getRandomValues(rnds8);
    }
getRandomValues doesn't specify a minimum amount of entropy.
reply
Hizonner
2 hours ago
[-]
It's a near certainty that something is badly wrong with the RNG, and, yes, probably in how it's seeded.

It's probably messing up the cryptography, too.

reply
Onavo
6 minutes ago
[-]
But defaults should be sane and safe. RNG isn't the sort of thing you want to be messing up. Every JS dev was taught that Math.random is not safe by default, but the crypto package is.
reply
adyavanapalli
7 hours ago
[-]
What you're talking about is so extremely rare that it's much more likely that the entire Earth is destroyed by an asteroid right this inst...
reply
delichon
4 hours ago
[-]
About as rare as an asteroid typing an ellipsis and clicking the add comment button.
reply
throw0101c
1 minute ago
[-]
Well, this joke dates back to (at least) the dial-up days where ($^&@$#(^@ NO CARRIER
reply
crazylogger
1 hour ago
[-]
For a single database using UUIDs, yes, it's astronomically rare. But it's quite a different thing to say that no computer system on Earth has ever experienced a UUID collision. The number of systems out there is also astronomical.
reply
nathanmills
11 minutes ago
[-]
>The number of systems out there is also astronomical.

Not even close

reply
sebazzz
2 hours ago
[-]
Well it would be statistically even rarer for that UUID collision to happen and the earth to be destroyed by an asteroid.
reply
merlindru
2 hours ago
[-]
Gotta be a seeding issue. If it's not, and you can prove it, you're about to be a little famous probably :P
reply
mittermayr
8 hours ago
[-]
I fully agree. It makes no sense. Yet...

The only guesses I'm having is that we originally generated UUIDv4s on a user's phone before sending it to the database, and the UUID generated this morning that collided was created on an Ubuntu server.

I don't fully know how UUIDv4s are generated and what (if anything) about the machine it's being generated on is part of the algorithm, but that's really the only change I can think of, that it used to generated on-device by users, and for many months now, has moved to being generated on server.

reply
AntiUSAbah
7 hours ago
[-]
You let users generate a UUID?

To be honest, the chance that you are doing something weird is probably higher than you experiencing a real UUID conflict.

How did your database 'flag' that conflict?

reply
wongarsu
4 hours ago
[-]
If it's UUIDv4 and you validate that the UUID is valid and not conflicting I don't really see the issue with user-generated UUIDs. Being able to generate unique keys in an uncoordinated manner is the main selling point of UUIDs

Sure, it's something I'd flag in any design to spend two minutes to talk about potential security implications. But usually there aren't any

reply
AntiUSAbah
3 hours ago
[-]
Validation etc. every thing which should not be controlled by a user, will not be controlled by a user.
reply
mittermayr
7 hours ago
[-]
user-generated (as in: on the user's phone) was only at the very early stages of this product, and we've since moved to on-server. It's a cash-register type of app, where the same invoice must not be stored twice. So we used to generate a fresh invoice_id (uuidv4) on the user's device for each new invoice, and a double-send of that would automatically be flagged server-side (same id twice). This has since moved on to a server-only mechanism.

The database flagged it simply by having a UNIQUE key on the invoice_id column. First entry was from 2025, second entry from today.

reply
wongarsu
4 hours ago
[-]
If it was two on-device generated UUIDs I could see a collision happening. There have been instances of cheap end devices not properly seeding their random number generators, leading to colliding "random" values. And cases of libraries using cheap RNGs instead of a proper cryptographic RNG, making it even worse

But on a server that shouldn't happen, especially not in 2026 (in the past, seeding the rngs of VMs used to be a bit of an issue). Even if one UUID was badly generated, a truly random UUID statistically shouldn't collide with it. You'd need an issue in both generators

reply
stubish
7 hours ago
[-]
The UUIDv4 collision is statistically extremely unlikely. What is more likely is both systems used the same seed. This might be just a handful of bytes, increasing the chance of collision to one in billions or even millions.
reply
lazyjones
6 hours ago
[-]
Better check what crypto.js is actually doing in your exact setup. Weak polyfills exist...
reply
baq
12 minutes ago
[-]
the vm you're running on virtualized all the entropy away.
reply
Geee
5 hours ago
[-]
According to the many-worlds interpretation of quantum mechanics, there's bound to be one branch of universe where every UUID is the same. Can you imagine what those guys are thinking?
reply
zeeveener
11 minutes ago
[-]
"Huh, this is just an identity function. Cool. Let's move on."
reply
nyantaro1
3 hours ago
[-]
This is why I am not a fan of the Everett approach
reply
tumdum_
6 hours ago
[-]
Poorly seeded prng.
reply
jdthedisciple
6 hours ago
[-]
most likely the culprit indeed
reply
nswango
6 hours ago
[-]
But I used nonstandard nonces!
reply
leni536
6 hours ago
[-]
It's not happening by chance, there is a bug somewhere.

From what I skimmed the package should just call to the js runtime's crypto.randomUUID(). I think it should always be properly seeded.

I think it is extremely unlikely that the runtime has a bug here, but who knows? What js runtime do you use?

reply
jordiburgos
7 hours ago
[-]
Please, do not use b6133fd6-70fe-4fe3-bed6-8ca8fc9386cd, I checked my database and I was using it already.
reply
rich_sasha
5 hours ago
[-]
I always thought generating UUIDs at random was insane. I now only use LLMs. The prompt is: "generate a UUID. Make sure no one ever used it anywhere in their code or database. Check your work and think hard about each step. Do not output any reasoning or plain English, only th UUID itself".

You're welcome.

reply
ktm5j
1 minute ago
[-]
What a great use of computing resources and electricity..
reply
mh2753
2 hours ago
[-]
Actually asking ChatGPT this query led it giving me this UUID "550e8400-e29b-41d4-a716-446655440000" which happens to be a very common example UUID
reply
mittermayr
7 hours ago
[-]
I knew it, we're all getting the same cheap UUIDs and the good ones are reserved for the big dogs.
reply
Galanwe
7 hours ago
[-]
uuid.uuidv4() recently switched to "adaptive entropy" instead of "xmax entropy" in an effort to save costs on non-premium users.
reply
robshep
7 hours ago
[-]
I'm using 16b55183-1697-496e-bc8a-854eb9aae0f3 and probably some more too. I suppose if we all post our list here, then we can all check for duplicates?
reply
jsnell
6 hours ago
[-]
You can check https://everyuuid.com/ for collisions.
reply
mittermayr
6 hours ago
[-]
We should all send our already-generated UUIDs to a shared database, we could just put it on Supabase with a shared username/password posted on HN, so we can all ensure that after generating a UUIDv4 locally, it's not used by anyone else. If it's in the database, we know it's taken.

It's a super simple mechanism, check in common worldwide UUID database, if not in there, you can use it. Perhaps if we use a START TRANSACTION, we could ensure it's not taken as we insert. But that's all easy, I'll ask Claude to wire it up, no problem.

reply
broken-kebab
6 hours ago
[-]
But then I will claim I have already used all the UUIDs in my spreadsheets, and my lawyer will send cease&desist letters to every database.
reply
volemo
6 hours ago
[-]
A site previously posted here could be useful: https://everyuuid.com/
reply
classified
5 hours ago
[-]
That UUID should have my name sticker on it. Don't your UUIDs have name stickers?
reply
serf
8 hours ago
[-]
1 in 4.72 × 10²⁸

1 in 47.3 octillion.

i'd be suspecting a race condition or some other naive mistake, otherwise id be stocking up on lottery tickets.

(lol at the other user posting at the same time about the lottery ticket.. great minds and all that.)

reply
petee
5 hours ago
[-]
I've always looked at it the the other way - being that lucky would mean you have even less chance of something else lucky happening, good time to save your money
reply
k4rli
3 hours ago
[-]
The lottery ticket part makes no sense. Statistically if such an improbable event just happened to him, then chance of it happening again should be even more improbable.
reply
sowbug
4 minutes ago
[-]
This is probably (ha) a troll thread, but in case anyone here is among today's lucky (ha) 10,000, https://en.wikipedia.org/wiki/Independence_(probability_theo...
reply
jaccola
5 minutes ago
[-]
The chance of him winning the lottery is identical to before, however the reward if he wins is slightly greater.

He would win the lottery money + he gets to tell people who don’t understand independence this incredible story!

reply
NKosmatos
6 hours ago
[-]
> I thought this is technically impossible

Actually it's not impossible, but very very improbable.

P.S. You should play a lottery/powerball ticket

P.P.S. Whenever I use the word improbable, the https://hitchhikers.fandom.com/wiki/Infinite_Improbability_D... comes in mind

reply
sebazzz
2 hours ago
[-]
> P.S. You should play a lottery/powerball ticket

Actually, they should not. That collision and winning the lottery would be even rarer.

reply
rithdmc
3 hours ago
[-]
Inconceivable!
reply
glaslong
6 hours ago
[-]
Buy some lava lamps
reply
beardyw
8 hours ago
[-]
Just a stupid question, but why not append the date, even in seconds as hex. It's just a few bytes and would guarantee that everything OK now will be OK in the future?
reply
flohofwoe
7 hours ago
[-]
You can just use a different UUID variant which includes timestamp data instead (e.g. v1 or v7), there are also variants which include the MAC address.
reply
mittermayr
8 hours ago
[-]
yeah, any sort of additional semi-random data could've helped prevent this, I'm sure. That, however, is also kind of the idea of UUIDv4, it has lots of randomness and time built in already.
reply
flohofwoe
7 hours ago
[-]
UUID v4 consists of only random bits, no timestamp info.
reply
mittermayr
7 hours ago
[-]
oh, interesting, I didn't know that and this could possibly be part of the problem perhaps depending on what's used as the seed.
reply
beardyw
4 hours ago
[-]
But surely hashing the date still allows for a future collision. Leaving the date as is means it will never collide after that one second has passed.
reply
kayodelycaon
7 minutes ago
[-]
UUID 7 does not hash the date. It uses 48 bits to store a millisecond resolution timestamp. This allows you to sort uuids by time.
reply
pan69
7 hours ago
[-]
> but why not append the date

And use uuid v5 to hash it :)

reply
lyfeninja
5 hours ago
[-]
Although incredibly rare, it's not impossible so probably best to just plan for collisions. A simply retry should suffice. But I agree I feel like something is going on somewhere else ...
reply
wg0
8 hours ago
[-]
Would the UUID v7 be more collision proof? Hard to say because it takes time into account but then the number of entropy bits are reduced hence the UUID generated exactly at the same time have more chance of a collusion because number of entropy bits are a much smaller space hence could result in collusions more easily.

Thoughts?

reply
AntiUSAbah
7 hours ago
[-]
You open up every millisecond a new block. Should be even more unlikely
reply
not_math
6 hours ago
[-]
Reminds me of some code I saw running in production. Every time we added a new entry, we were pulling all the UUIDs from this table, generating a new UUID, and checking for collisions up to 10 times.
reply
OutOfHere
3 hours ago
[-]
This is why I prefer to use a random base32 string over UUID. At least you get a proper 128 bit entropy instead of just a 122 bit entropy as with UUIDv4. That's a 64x difference in collision probability. I always thought UUIDs were a toy, not for serious use. If you control the strings, you can even make a longer ID.

Also, numerous applications that use a unique ID per record frequently need to check for ID collisions. I know I do for a short URL generator.

reply
AndreyK1984
6 hours ago
[-]
Why not to have timestamp-uuid instead ?
reply
dgellow
6 hours ago
[-]
How confident are you that your machines clocks are in perfect sync? What about the risk of clock drift + correction, or hardware issues?
reply
croon
4 hours ago
[-]
Not GP, but: not confident. How confident would I be to avoid a (slightly lower entropy) UUID collision while also avoiding a clock desync landing on the exact same logged millisecond? Very, which is how confident I was about not encountering an UUID collision before this thread, so very++ I guess.
reply
naikrovek
7 hours ago
[-]
The chance of a UUIDv4 collision is very low, but it is never zero.

If everything is done properly, then this is very likely the one and only time anyone involved in the telling or reading of this account will ever experience this.

reply
dalmo3
7 hours ago
[-]
Classic gamblers fallacy!
reply
sublinear
5 hours ago
[-]
reply
ares623
6 hours ago
[-]
Buy a lottery ticket
reply