UUID generator
Generate UUIDs — random v4 or time-ordered v7 — one at a time or in batches.
122 random bits. Reveals nothing about when it was created.
Generating…
What a UUID is and why it exists
A UUID — Universally Unique Identifier, also called a GUID in Microsoft documentation — is a 128-bit value written as 32 hexadecimal digits in the familiar 8-4-4-4-12 grouping. Its whole purpose is to let separate systems mint identifiers independently, with no coordination between them, and still be confident the results will not collide. That is what makes it different from a database auto-increment column: two servers, two mobile clients offline on a plane, and a background job can all create records at the same moment without asking anyone for permission.
Uniqueness here is probabilistic rather than guaranteed. Version 4 leaves 122 bits to randomness, which is a large enough space that generating billions of values still leaves the chance of a repeat far below the chance of a disk silently corrupting the data instead. In practice you can treat it as unique; the maths is not the weak link.
Version 4 vs. version 7 — the choice that matters
Version 4 is random from end to end. It carries no information whatsoever: not when it was made, not by whom, not in what order. That is either its greatest strength or its central flaw, depending on where you put it.
Version 7, standardised in RFC 9562 in 2024, replaces the first 48 bits with a millisecond Unix timestamp and fills the rest with randomness. Because the time comes first and the value is read left to right, sorting v7 identifiers as plain text also sorts them chronologically.
This is not a cosmetic difference. Databases keep primary keys in a sorted B-tree index. Insert v7 keys and each new row lands at the right-hand edge of the tree, next to the previous one — the pages you are writing to stay in memory and the index grows tidily. Insert v4 keys and every write lands at a random position, so the database touches a different page each time, cache hit rates fall and the index fragments. On a large, busy table the difference in insert throughput is substantial, which is why v7 has been adopted so quickly for primary keys.
- Choose v7 for database primary keys, event and log identifiers, and anything you will want to sort or range-query by creation time.
- Choose v4 when the identifier appears somewhere untrusted and must leak nothing — including the fact that one record was created just before another.
- Either is fine for a correlation ID, an idempotency key or a file name, where ordering does not matter.
The trade-off is exactly that leak: a v7 identifier tells anyone who sees it, to the millisecond, when it was created. For a row ID that is usually harmless and often useful. For a password-reset token or a public share link it is information you did not mean to publish — and those should not be UUIDs at all, but random tokens from a dedicated secret generator.
Ordering within the same millisecond
A subtlety that catches many v7 implementations: modern hardware generates far more than one identifier per millisecond. If two values share a timestamp, their order is decided by the random bits that follow — which is to say, at random. Generate fifty in a tight loop and you get fifty values that are only roughly ordered, losing precisely the property you chose v7 for.
RFC 9562 addresses this with a monotonic counter, and this tool implements it: the 12 bits immediately after the timestamp count upward within a millisecond, so a batch is strictly increasing rather than approximately so. If the counter fills — more than 4096 values in the same millisecond — the generator borrows the next millisecond instead of wrapping around and emitting a value that sorts before its predecessor. It handles the clock moving backwards, which happens with NTP corrections, the same way.
Reading a v7 value left to right, taking 0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b as the example:
- 0190a1b2-c3d4 — the 48-bit Unix timestamp in milliseconds. Because it comes first, text order is time order.
- 7 — the version nibble, which is what makes this a v7 rather than a v4.
- e5f — the 12-bit monotonic counter, incrementing within a single millisecond.
- 8 — the variant bits, fixed by RFC 9562 for every modern UUID (always 8, 9, a or b).
- a9b-0c1d2e3f4a5b — the remaining 62 bits, purely random.
Storing and using UUIDs
The canonical form is lowercase with hyphens, and RFC 9562 says generators should emit exactly that — which is why this tool offers no formatting options. You will still meet other spellings in the wild: uppercase and wrapped in braces in Microsoft tooling, and stripped of hyphens where someone wanted a shorter column. They are all the same 128 bits, and comparisons should be case-insensitive.
Where it counts is storage. A UUID is 16 bytes, but the text form is 36 characters — so storing it as a string more than doubles the space in the row and, more importantly, in every index that includes it. Use a native type where one exists:
uuid -- PostgreSQL: native 16-byte type BINARY(16) -- MySQL: compact; CHAR(36) wastes 20 bytes/row uniqueidentifier -- SQL Server crypto.randomUUID() // JavaScript: v4 only, needs a secure context uuid.uuid4() / uuid7() # Python: stdlib v4; v7 via a library
One last caution: a UUID identifies, it does not authorise. Because they are unguessable, it is tempting to treat an unlisted URL containing one as private. But identifiers leak — through logs, browser history, referrer headers and screenshots — so anything that actually needs protecting still needs a real permission check behind it.
Frequently asked questions
- Should I use v4 or v7?
- Use v7 for database primary keys and anything you will sort by creation time: the leading timestamp keeps inserts clustered at the end of the index instead of scattered across it. Use v4 when the identifier must reveal nothing at all, including when it was created.
- Are two UUIDs ever the same?
- It is possible but vanishingly unlikely. Version 4 has 122 random bits, so even after generating billions of values the probability of a collision stays far below the probability of the storage silently corrupting them instead.
- What happened to versions 1, 3 and 5?
- Version 1 encodes a timestamp and the machine's MAC address, which leaks hardware identity and cannot be produced in a browser at all. Versions 3 and 5 derive a UUID deterministically from a namespace and a name using MD5 or SHA-1 — useful when the same input must always produce the same identifier, but a different job from generating a fresh one.
- Is a UUID secure enough to use as a secret token?
- A v4 UUID is unguessable, but a v7 one openly encodes its creation time, and neither is meant as a credential. For password resets, session tokens or share links, generate a dedicated random secret and check permissions on the server rather than relying on the identifier being hard to guess.
- Why is my v7 batch not perfectly sorted in other tools?
- Because many implementations skip the monotonic counter. When several values share a millisecond, their order falls to the random bits that follow. This tool implements RFC 9562's counter, so a batch generated here is strictly increasing.
- How should I store a UUID in a database?
- In a native 16-byte type where one exists — uuid in PostgreSQL, uniqueidentifier in SQL Server, BINARY(16) in MySQL. Storing the 36-character text form instead more than doubles the space used in the row and in every index that includes the column.
- Are these generated on your servers?
- No. They are generated in your browser using crypto.getRandomValues, the platform's cryptographic random source — the same one crypto.randomUUID uses. No value is ever sent anywhere, and reloading the page produces an entirely fresh set.