๐ UUID Generator v1 ยท v4 ยท v7
UUID v1, v4, and v7 Explained โ A Developer's Practical Guide
Every time you create a database record, a file upload, a session token, or an API resource, you need an identifier that is unique across every machine in your fleet, forever. UUIDs (Universally Unique Identifiers) solve exactly this problem โ and not all UUIDs are created equal. The version you choose has real consequences for database performance, debuggability, and security.
This guide walks you through the three most useful UUID versions in 2025 โ v1, v4, and v7 โ explains how each one actually works under the hood, and tells you exactly which version to reach for in each situation.
What Is a UUID, Structurally?
A UUID is 128 bits of data, conventionally displayed as 32 hexadecimal characters split into five groups: xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx. The M position (group 3, first character) is the version digit. The N position (group 4, first character) encodes the variant โ for the RFC 4122 / RFC 9562 standard it is always 8, 9, a, or b, meaning the top two bits are 10 in binary.
That is the entire structure. Everything else โ whether the remaining bits encode a timestamp, a MAC address, or pure randomness โ depends on the version.
UUID v4 โ Pure Randomness, Zero State
UUID v4 is the most widely deployed version. Exactly 122 of its 128 bits are set by a cryptographically secure random number generator (CSPRNG). The remaining 6 bits are reserved for the version nibble and the variant bits. An example looks like this:
3839d769-a6de-4a65-a4c2-30cc4de01490
Because it is pure random, v4 requires no coordination between machines. There is no shared clock, no central counter, no MAC address exposure. The collision probability for a single pair of v4 UUIDs is approximately 1 in 5.3 ร 1036 โ effectively zero for any real workload.
When to use v4: Default choice for primary keys when you are starting fresh, for API tokens, session IDs, file upload keys, and anything where you need opaque identifiers. The randomness also means v4 UUIDs do not leak information about when a record was created โ useful for public-facing IDs.
The one drawback: Because v4 UUIDs are completely random, inserting them as primary keys in a B-tree index (like PostgreSQL's default btree or MySQL's InnoDB) causes frequent page splits. At high insert rates this becomes measurable. Enter v7.
UUID v7 โ Sortable and Modern
UUID v7 was formally standardized in RFC 9562 (2024). It packs a 48-bit Unix millisecond timestamp into the most significant bits, followed by a version nibble, 12 random bits (rand_a), a 2-bit variant marker, and 62 random bits (rand_b). The structure looks like:
019ef821-369d-7142-81a0-d62243d447c4
โ โ โ
ms timestamp version=7 random suffix
The 48-bit timestamp in the first group means that when you sort v7 UUIDs lexicographically, they come out in the order they were generated โ to the millisecond. Two UUIDs generated in the same millisecond are disambiguated by the random suffix. This property makes v7 an excellent drop-in replacement for auto-increment integers when you want globally unique IDs without a centralized sequence.
Database performance: Because new UUIDs are always larger than old ones (later timestamp), they always append to the rightmost page of the index. B-tree page splits stop. Benchmarks on PostgreSQL with UUID v7 keys show insert throughput comparable to BIGSERIAL while retaining global uniqueness. Libraries like uuid_generate_v7() in pg_uuidv7 or the built-in support in Postgres 17+ make adoption straightforward.
When to use v7: New greenfield projects, microservice event logs where ordering matters, any table that will grow beyond a few million rows and is indexed on the primary key, and distributed systems where you want to recover approximate creation time from the ID itself without a separate created_at column query.
UUID v1 โ Time-Based with Node Identity
UUID v1 is the oldest version and the most information-rich. It encodes a 60-bit timestamp counting 100-nanosecond intervals since October 15, 1582 (the start of the Gregorian calendar โ a quirky but intentional choice), a 14-bit clock sequence to handle rapid generation or clock resets, and a 48-bit node identifier.
Originally the node was meant to be the MAC address of the generating machine, which guaranteed uniqueness across machines without coordination. However, embedding a MAC address is a significant privacy concern โ it was famously used to trace the author of the Melissa worm. Modern implementations use a cryptographically random node instead, sacrificing true uniqueness guarantees for privacy.
A v1 UUID looks like:
ab5e7710-6f8e-11f1-b8eb-41dc2350fc71
Note that the timestamp is stored in a peculiar byte order: time_low (32 bits) comes first, then time_mid (16 bits), then time_hi (12 bits) with the version nibble. This means v1 UUIDs are not directly sortable as strings โ the timestamp is scrambled across the groups.
When to use v1: Legacy systems that already use v1, or niche cases where you need the embedded timestamp and are comfortable parsing it back out. For new work, v7 is strictly better: it is also time-ordered, actually sortable, and does not have the odd timestamp byte ordering.
Formatting Options โ Case and Hyphens
The canonical UUID format is lowercase with hyphens, as specified in RFC 4122. Both uppercase and hyphen-stripped variants are widely accepted, but you should pick one and enforce it consistently throughout a project. Storing 3839D769A6DE4A65A4C230CC4DE01490 in one service and 3839d769-a6de-4a65-a4c2-30cc4de01490 in another will cause lookup failures if you ever join or compare without normalization.
The hyphen-stripped format saves 4 bytes per UUID in storage and network transfer โ negligible in most cases but occasionally relevant in high-throughput event streams or fixed-width binary formats. Some systems (notably Microsoft COM/OLE) traditionally use uppercase with curly braces; most web APIs expect lowercase with hyphens.
Generating UUIDs in Code
In modern environments, UUID generation is built-in or one import away. In Node.js 19+ and all modern browsers, crypto.randomUUID() generates a cryptographically secure v4 UUID with no dependencies. In Python, the uuid module in the standard library covers v1, v3, v4, and v5 โ and third-party packages like uuid7 add v7. In Go, the google/uuid package added v7 support in v1.6. PostgreSQL users can install the pg_uuidv7 extension or use Postgres 17's native uuidv7() function.
Quick Decision Guide
If you need simplicity and privacy, use v4. If you need index performance and time ordering in a new project, use v7. If you are maintaining a legacy system that already uses v1, keep using v1 โ migrating UUID versions mid-project is painful without a clear benefit. Never roll your own UUID algorithm; the bit-level details of version nibbles and variant markers are easy to get slightly wrong in ways that cause subtle collisions or interoperability failures with strict parsers.
The generator above handles all three versions in pure client-side JavaScript using crypto.getRandomValues() for all random bytes, so nothing is ever sent to a server. Generate your batch, choose your format, and copy โ ready to paste into your migration file, Postman, or seed script.