UUID Generator
v4 is 122 random bits — unpredictable, and the right choice when the ID must reveal nothing. Random ordering makes it a poor database primary key.
Nothing you enter here is stored, logged or shared.
Generate UUIDs in your browser, either random v4 or time-sortable v7. Choose how many you need and copy them individually or all at once.
How to use
- Pick v4 for random IDs or v7 for time-sortable ones.
- Choose how many to generate.
- Copy a single value, or use Copy all.
What the 128 bits hold
A UUID is sixteen bytes, written as 32 hexadecimal digits in the familiar 8-4-4-4-12 grouping. Not all of them are free: four bits identify the version, and two or three more identify the variant, which is why the thirteenth digit of every UUID here is a 4 or a 7, and the seventeenth is always one of 8, 9, a or b.
That leaves 122 bits for a version 4 UUID to fill randomly. Version 7 spends the first 48 of its bits on a millisecond timestamp and fills the remaining 74 with randomness, trading some unpredictability for order.
The hyphens carry no information and neither does the case, though RFC 9562 says to output lowercase and accept either on input. The urn:uuid: prefix and the braces that Windows tooling likes are presentation, not content.
Why v7 exists
Version 4 UUIDs are uniformly random, which is exactly what you want for an identifier that should reveal nothing, and exactly what you do not want for a primary key.
A B-tree index keeps its entries in sorted order. Insert a random key and it lands anywhere in that order, so each insert touches a different page, and once the working set of pages exceeds memory every insert becomes a read as well as a write. Pages fill unevenly and split, the index grows larger than the data it indexes, and write throughput degrades as the table grows. With sequential keys, inserts land at the end, one page stays hot, and none of this happens.
Version 7 puts a timestamp in the high bits so that IDs generated later sort after ones generated earlier, restoring that locality while keeping global uniqueness and needing no coordination between machines. It is the reason RFC 9562 added it, and it is the right default for a key column now.
The trade is real: a v7 UUID discloses roughly when the row was created, and consecutive ones reveal ordering and rough rate. Where an identifier is exposed publicly and either of those is sensitive, v4 is still the right choice.
Collisions
Two version 4 UUIDs collide when 122 random bits repeat. The usual way to make that number legible is the birthday bound: you would need to generate about a billion UUIDs a second for around 85 years before the chance of a single collision anywhere in the set reached 50%.
So in practice, no. The realistic failure modes are not statistical. They are a generator seeded badly - virtual machines cloned from the same snapshot, embedded devices with no entropy at boot - or code that truncates a UUID to fit a column and destroys most of the randomness, or a library that quietly falls back to a non-cryptographic source. The bits here come from the browser's cryptographic generator, and the useful habit elsewhere is to check what your library actually uses rather than assuming.
Storing them
The text form is 36 characters. The value is 16 bytes. Storing UUIDs as char(36) more than doubles the space and, in databases where every secondary index carries a copy of the primary key, multiplies that cost across the whole schema.
PostgreSQL has a native uuid type that stores 16 bytes and accepts the text form on input. MySQL has no such type; the conventional approach is binary(16) with conversion at the boundary, and for version 1 UUIDs there is a well-known trick of reordering the time bytes to restore sortability, which version 7 makes unnecessary.
If you display UUIDs in a URL and their length bothers you, encode the same 16 bytes in base32 or base64url rather than shortening the value. Truncation looks like it works right up until it does not.
The full set of versions
Version 1 encodes a 60-bit timestamp and the machine's MAC address, which makes it sortable and traceable - the second property is why it fell out of favour, since it leaks which machine generated an identifier. Version 2 is a DCE security variant almost nobody uses. Version 3 and version 5 are deterministic: they hash a namespace and a name, with MD5 and SHA-1 respectively, so the same input always produces the same identifier.
Version 4 is pure randomness and became the default everywhere because it needs no coordination, no clock and no machine identity. Version 6 is version 1 rearranged so the timestamp sorts correctly, and version 7 is the modern answer: a millisecond timestamp in the high bits followed by randomness, standardised in RFC 9562 in 2024.
Version 5 deserves more use than it gets. When you need a stable identifier derived from something you already have - a URL, a file path, a tenant name - hashing it into a UUID gives every system the same identifier without a lookup table or a coordination step.
The alternatives, and when they fit better
ULID encodes a timestamp and randomness into 26 characters of Crockford base32: sortable, case-insensitive, and shorter than a UUID in text form. It predates version 7 and solves the same problem, so new systems can usually just use v7 and stay inside the standard.
Snowflake identifiers, from Twitter originally, pack a timestamp, a machine id and a sequence number into 64 bits. They are compact, sortable and coordination-light, at the cost of requiring each node to have a distinct id. They also exceed what a JavaScript number holds exactly, which is why APIs that use them return strings.
nanoid produces short random strings for URLs, with a configurable alphabet - the default 21 characters carries roughly the same entropy as a v4 UUID in half the text. And an ordinary auto-incrementing integer is still the best choice in plenty of systems: smallest, fastest to index, and perfectly fine when identifiers stay internal.
What an identifier reveals when it is public
Sequential integers in public URLs tell everyone your volume and let anyone walk the range: /orders/1001 implies /orders/1000 exists. Combined with a missing authorisation check, that is the vulnerability class known as insecure direct object reference, which remains one of the most commonly found flaws in web applications.
A random v4 UUID removes the enumeration, and only that. It is not an access control: an identifier nobody can guess is still an identifier anyone who obtains it can use, and URLs leak through referrer headers, browser history, logs, screenshots and shared links. Every request still needs to check that this user may see this resource.
Version 7 trades a little of that opacity back. It discloses roughly when a record was created, and consecutive identifiers reveal ordering and rate - enough to infer how many customers signed up in a week. Where either is sensitive in a public identifier, use v7 internally as the primary key and expose a v4 or a separate slug.
Primary keys, indexes and storage
A B-tree index keeps entries sorted, so random keys scatter inserts across the whole index. Once the index no longer fits in memory each insert becomes a read as well as a write, pages fill unevenly and split, and write throughput falls as the table grows. Sequential keys append to the end, keep one page hot, and avoid all of it - which is the entire argument for version 7.
Storage matters too. A UUID is 16 bytes; its text form is 36 characters. PostgreSQL has a native uuid type that stores the binary form and accepts text on input. MySQL has no such type, so the convention is BINARY(16) with conversion at the application boundary. Storing text instead more than doubles the space, and in engines where every secondary index carries a copy of the primary key, that cost multiplies across the schema.
The common middle path is a small integer primary key for internal joins and a UUID as an external identifier with a unique index. It keeps the physical layout tight while still giving the outside world an opaque handle.
Generating them safely in code
Use the platform function rather than assembling one by hand: crypto.randomUUID in browsers and Node, uuid4 in Python, UUID.randomUUID in Java. These draw from the cryptographic generator, which is what makes the collision argument hold. A library that falls back to Math.random - some older JavaScript packages did - produces identifiers that look identical and are predictable.
The realistic failure modes are not statistical. Virtual machines cloned from the same snapshot can start with the same entropy pool; embedded devices may have almost none at boot; and code that truncates a UUID to fit a column destroys most of the randomness while leaving something that still looks like an identifier.
Two habits avoid the rest. Compare identifiers case-insensitively, since RFC 9562 says to emit lowercase but accept either, and strip the braces and urn:uuid: prefix that Windows tooling adds. And validate on input rather than trusting the shape, because a UUID-looking string in a URL is still user input.
Frequently asked questions
- What is the difference between UUID v4 and v7?
- v4 is 122 random bits, so it reveals nothing and is unpredictable. v7 begins with a 48-bit millisecond timestamp followed by random bits, so IDs generated later always sort after earlier ones. v4 hides creation time; v7 exposes it but sorts.
- Which one should I use for a database primary key?
- v7. Random v4 keys scatter inserts across the whole index, which fragments B-tree pages and hurts write throughput and cache locality. v7 keys are appended in order, behaving much more like an auto-incrementing integer while staying globally unique.
- Are these UUIDs cryptographically random?
- Yes. The random bits come from crypto.getRandomValues, the browser cryptographically secure random number generator, not Math.random. A v4 UUID has 122 random bits, so collisions are not a practical concern.
- Why is there no v1 or v5 option?
- v1 encodes a MAC address and clock state, which leaks host identity, and RFC 9562 points new systems to v7 instead. v3 and v5 are name-based: they hash a namespace plus a name to produce a deterministic ID, which needs its own inputs and belongs in a separate tool.
- Are the UUIDs generated on a server?
- No. They are generated in your browser and never transmitted, so nobody else, including this site, ever sees them.
- What is the difference between a UUID and a GUID?
- Nothing, in practice. GUID is Microsoft naming for the same 128-bit identifier, which is why Windows tooling often shows it in braces. Use the braces option if you need that form.
Last updated:
Include the steps, expected result, and actual result. Remove secrets and personal data.
