Version 4 and the collision question
A version 4 UUID is 128 bits of which 122 are random, the other six being fixed version and variant markers. That gives roughly 5.3 × 10³⁶ possible values, and the practical question is never "could two collide" but "how many can I generate before a collision becomes plausible".
By the birthday bound, you would need to generate about 2.7 × 10¹⁸ UUIDs before reaching a 50 percent chance of any collision — around a billion per second for 85 years. For any realistic application the risk is negligible, and it is entirely reasonable to treat v4 UUIDs as unique without a uniqueness check.
The assumption that matters is randomness quality. This generator uses crypto.getRandomValues, the browser's cryptographically secure source. A UUID built from Math.random has far less real entropy than its 122 bits suggest and can repeat, which is a genuine bug in libraries that have made that choice.
Why v1 leaks and v7 exists
Version 1 UUIDs encode a timestamp and, in the original specification, the generating machine's MAC address. This makes them predictable and identifying — a v1 UUID discloses roughly when it was created and on which network interface, which has been used in real forensic work to attribute documents. Avoid v1 for anything public-facing.
But v4's pure randomness has a cost that shows up at scale. Databases store primary keys in sorted structures, and random keys scatter inserts across the whole index, causing page splits, poor cache locality and index fragmentation. On a large table, random UUID keys measurably degrade insert throughput compared with sequential integers.
Version 7, standardised in RFC 9562 in 2024, resolves this: a 48-bit millisecond timestamp followed by random bits. Values sort chronologically, so inserts land at the end of the index like an auto-increment key, while retaining enough randomness to be unguessable. For new systems using UUIDs as database keys, v7 is the right default; v4 remains correct wherever the value must reveal nothing at all, including its creation time.
Identifiers are not authorisation
The most consequential mistake with UUIDs is treating unguessability as access control. Exposing a document at a URL containing a v4 UUID and performing no permission check is security by obscurity, and URLs leak constantly — through referrer headers, browser history, shared links, proxy logs, screenshots and pasted messages. Every request still needs an authorisation check.
For a genuinely unguessable capability URL, a UUID is also not the ideal instrument. It has a recognisable shape that invites enumeration attempts, and 122 bits arrives in a format optimised for readability rather than density. A random token from the password generator is more compact for the same entropy.
On storage: a UUID is 16 bytes as binary and 36 characters as text. Storing it as a string in a database costs more than twice the space, plus slower comparisons, and multiplies across every index and foreign key. Use the native UUID type where the database has one.