logo

Ask HN: We just had an actual UUID v4 collision...

Posted by mittermayr |4 hours ago |12 comments

samdhar 4 hours ago

The math says no. UUID v4 has 122 bits of randomness, so collision probability for 15K records is N²/(2·2^122) ≈ 2·10^-29. That's somewhere around "fewer collisions per universe lifetime than atoms in your liver." Whatever you're seeing, the culprit is overwhelmingly somewhere else.

Things to check, in descending order of how likely they actually are:

1. Data import / migration / backup restore, perhaps? Did anyone load a CSV, run a seed script, restore a snapshot, or copy rows between environments at any point in the last year? This is what "duplicate UUID" is in 99% of cases. Check git on migrations, ops history on the DB, and ask anyone who might have been moving data around.

2. Application retry / rollback bug maybe? Code path that generates a UUID, attempts insert, fails on constraint violation, retries with the same UUID variable still in scope. Check whether UUID generation lives inside or outside the retry boundary.

3. Older versions of the uuid package in certain bundler environments would fall back to Math.random() instead of crypto.getRandomValues(). What version are you on? Anything <4.x is suspect; modern v8+/v9+ uses crypto everywhere correctly.

4. Could also be a process fork bug. If a UUID generator runs in a child process spawned from a parent that already used the PRNG, the entropy state can get copied. Rare in Node specifically, more historical in old Python/Ruby setups.

If you've ruled all of those out and the row really was generated independently a year apart via crypto.getRandomValues, go buy a lottery ticket. But it's almost certainly cause #1.

mittermayr 3 hours ago[1 more]

Not sure why the second comment was flagged (I didn't do it!), but I was able to read it and also the comment from serf, thanks.

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.

wg0 3 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?

jordiburgos 3 hours ago

Please, do not use b6133fd6-70fe-4fe3-bed6-8ca8fc9386cd, I checked my database and I was using it already.

beardyw 3 hours ago[2 more]

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?

serf 4 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.)

naikrovek 3 hours ago[1 more]

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.

ESAM_C 3 hours ago

Comment deleted