What Are UUIDs and Why Do They Matter?
UUIDs are 128-bit identifiers designed to be unique without coordination. Here's how they work, what changed with RFC 9562, why UUID v7 is replacing v4, and how collision probability actually works.
A UUID — Universally Unique Identifier — is a 128-bit value designed to be unique across all systems, all time, and all locations without requiring a central authority to coordinate assignments. No database lookup, no API call, no distributed lock — just generate a UUID locally and trust, with near-mathematical certainty, that nothing else in the world will produce the same value.
That property makes UUIDs one of the most widely used constructs in modern software. They serve as database primary keys, API resource identifiers, session tokens, message IDs, file names, correlation IDs in distributed tracing, and anywhere else a system needs a unique label without asking permission from a central registry. Our UUID generator creates them instantly, but understanding what you're generating — and which version to choose — matters more than most developers realize.
The Anatomy of a UUID
A UUID is 128 bits long, typically represented as 32 hexadecimal characters separated by hyphens into five groups: 8-4-4-4-12. A typical UUID looks like 550e8400-e29b-41d4-a716-446655440000. Despite the hyphens, the underlying value is just a 128-bit integer — the formatting is a display convention for human readability.
Within that 128-bit space, 4 bits are reserved for the version number (which identifies how the UUID was generated) and 2 to 3 bits are reserved for the variant (which identifies the UUID layout specification). This leaves 122 to 123 bits for the actual unique payload in most versions.
The version number occupies the four most significant bits of the seventh byte — the first character of the third group. If you see a UUID with a 4 in that position (like ...41d4...), it's a version 4 UUID. A 7 in that position indicates version 7. This makes the version visually identifiable in the string representation.
UUID Versions: A Brief History
The original UUID specification, RFC 4122, was published in 2005 and defined versions 1 through 5. In May 2024, RFC 9562 replaced it, retaining the original versions and adding versions 6, 7, and 8. Each version uses a different strategy to achieve uniqueness.
Version 1 combines a timestamp (the number of 100-nanosecond intervals since October 15, 1582 — the Gregorian calendar reform date) with the MAC address of the generating machine. This guarantees uniqueness as long as the clock and MAC address are unique, but it leaks information: anyone who reads a v1 UUID can determine when and on which machine it was generated. Privacy concerns have made v1 less popular in modern applications.
Version 2 is a variant of v1 used for DCE (Distributed Computing Environment) security. It replaces part of the timestamp with a local domain identifier. Version 2 is rarely encountered in modern software.
Version 3 generates a UUID by hashing a namespace identifier and a name using MD5. Given the same namespace and name, v3 always produces the same UUID. This is useful for creating deterministic IDs from string inputs, but MD5's known weaknesses make v3 less desirable than v5.
Version 4 generates a UUID from random or pseudorandom numbers. Of the 128 bits, 122 are random (6 bits are fixed for version and variant). Version 4 has been the dominant UUID version for the past decade because it's simple to implement, requires no state or coordination, and has an astronomically low collision probability. Our UUID generator produces v4 UUIDs by default.
Version 5 is identical to v3 in concept but uses SHA-1 instead of MD5 for the hash function. Given the same namespace and name, v5 always produces the same UUID. It's preferred over v3 for new implementations.
Version 6 (new in RFC 9562) is a reordered version of v1 that rearranges the timestamp bits so that UUIDs sort chronologically when treated as opaque byte sequences. This addresses one of v1's practical limitations — its timestamp bits are arranged in a way that doesn't sort naturally.
Version 7 (new in RFC 9562) is the most significant addition. It combines a Unix timestamp in milliseconds (48 bits) with random data (74 bits, after reserving bits for version and variant). Version 7 UUIDs are time-ordered, sort chronologically, contain no hardware identifiers, and have sufficient randomness to avoid collisions. UUID v7 is now the recommended choice for new database-backed applications.
Version 8 provides a format for custom, implementation-specific UUIDs. The specification reserves the version and variant bits but allows the remaining 122 bits to be filled with any data the implementation chooses.
Why UUID v7 Is Replacing v4
For years, UUID v4 was the sensible default. It's random, simple, and practically collision-proof. But v4 has a significant performance problem when used as a database primary key: randomness destroys index locality.
Databases like PostgreSQL, MySQL, and SQL Server store indexed data in B-tree structures. When you insert a row with a sequential primary key (like an auto-incrementing integer), the new row goes at the end of the index. The database only needs to modify the last leaf page of the B-tree. This is fast and cache-friendly.
When you insert a row with a random UUID v4 primary key, the new row could land anywhere in the index. The database must locate the correct leaf page, potentially loading it from disk if it's not in memory, insert the row, and possibly split the page. At scale — millions or billions of rows — this random insertion pattern causes significant write amplification, index fragmentation, and cache churn. Benchmarks consistently show that random UUID v4 primary keys produce 30 to 40 percent slower INSERT performance than sequential keys in B-tree-indexed tables.
UUID v7 solves this by front-loading the timestamp. Because v7 UUIDs begin with millisecond-precision Unix time, newly generated UUIDs are always greater than previously generated ones (within the same millisecond, the random component provides ordering). This means v7 UUIDs insert at the end of B-tree indexes, just like auto-incrementing integers, while retaining all the benefits of UUIDs: decentralized generation, no coordination required, and globally unique identifiers.
The trade-off is that v7 UUIDs reveal their creation time. The first 48 bits encode the Unix timestamp in milliseconds, which is trivially extractable. For most applications this is acceptable or even desirable (creation timestamps are often stored separately anyway), but for systems where the creation time of a resource must be confidential, v4 remains appropriate.
Collision Probability
The question everyone asks about UUIDs: what if two systems generate the same one? The answer requires understanding the birthday problem — a counterintuitive result from probability theory.
The birthday problem asks: in a group of people, how many do you need before there's a 50 percent chance that two share a birthday? The surprising answer is just 23 (for 365 possible birthdays). The collision probability grows much faster than intuition suggests because every new element can collide with every existing element.
For UUID v4, the "birthday space" is 2 to the 122nd power — approximately 5.3 times 10 to the 36th possible values. Applying the birthday problem formula, you would need to generate approximately 2.7 times 10 to the 18th UUIDs (2.7 quintillion) before reaching a 50 percent collision probability. To put that in perspective: generating one billion UUIDs per second, continuously, it would take approximately 86 years to reach a 50 percent chance of a single collision.
At more realistic scales, the numbers are even more reassuring. If your system generates one million UUIDs, the collision probability is approximately 10 to the negative 25th — effectively zero. At one billion UUIDs, the probability rises to approximately 10 to the negative 19th — still effectively zero. You would need to generate on the order of 10 to the 14th (one hundred trillion) UUIDs before the collision probability exceeds one in a billion.
These calculations assume a proper cryptographic random number generator. If the random source is weak, biased, or predictable, collision probability increases dramatically. This is why UUID generation should use cryptographically secure random functions — the same kind used by our password generator and random string generator.
UUIDs vs. Other ID Formats
UUIDs aren't the only option for unique identifiers. Several alternatives address specific limitations.
Auto-incrementing integers (1, 2, 3, ...) are the simplest primary key strategy. They're compact (4 or 8 bytes vs. 16 bytes for UUIDs), sequential (excellent B-tree performance), and human-readable. But they require a central counter (the database), leak information about your data volume (user ID 50,000 tells people you have about 50,000 users), and can't be generated offline or in distributed systems without coordination.
ULID (Universally Unique Lexicographically Sortable Identifier) is a 128-bit identifier that combines a 48-bit timestamp with 80 bits of randomness, encoded as a 26-character Crockford Base32 string. ULIDs predate UUID v7 and solve the same time-ordering problem. Now that UUID v7 is standardized in RFC 9562, ULIDs and UUID v7 are functionally similar, but UUID v7 has the advantage of being an official standard with broader library and database support.
NanoID generates shorter, URL-friendly identifiers using a customizable alphabet. A default NanoID is 21 characters using A-Z, a-z, 0-9, underscore, and hyphen — producing 126 bits of entropy. NanoIDs are popular in frontend applications and URL slugs where a 36-character UUID is unnecessarily long.
Snowflake IDs (originated by Twitter, now used by Discord and others) are 64-bit integers combining a timestamp, worker ID, and sequence number. They're time-ordered and compact but require centralized worker ID assignment and are limited to 64 bits.
For most server-side applications in 2026, UUID v7 is the recommended default. It's standardized, time-ordered, 128 bits, and supported by all major databases and programming languages.
UUIDs in Databases
How you store UUIDs in a database matters for performance. The worst approach is storing them as 36-character strings (varchar(36)) — this wastes space and makes comparisons slower. The best approach depends on your database.
PostgreSQL has a native uuid type that stores UUIDs as 16 bytes internally. This is the most efficient option for PostgreSQL and supports direct comparison, indexing, and conversion. Since PostgreSQL 17, the built-in gen_random_uuid() function generates v4 UUIDs natively.
MySQL and MariaDB support a BINARY(16) column type for efficient UUID storage, and newer versions include UUID_TO_BIN() and BIN_TO_UUID() functions for conversion. MySQL 8.0 introduced a uuid type in some contexts, but BINARY(16) with swap-flag optimization remains common.
SQL Server has a uniqueidentifier type that stores UUIDs as 16 bytes with native support for generation and comparison.
When using UUID v7 as a primary key with a clustered index (SQL Server) or as the leading column of a B-tree index (PostgreSQL, MySQL), the time-ordered property eliminates the page-split problem. This is the primary practical reason to prefer v7 over v4 for database primary keys.
UUIDs Are Not Passwords
A common misconception worth addressing: UUIDs are unique, but they are not secret. A UUID v4 has 122 bits of randomness, which makes it astronomically unlikely to guess by brute force. But UUIDs are designed for uniqueness, not for security. They're typically transmitted in URLs, stored in logs, exposed in API responses, and included in database records — none of which treat them as confidential.
If you need a secret token — for authentication, session management, or API keys — use a dedicated cryptographic random generator that produces the appropriate entropy for your security requirements. Our password generator and random string generator are designed for this purpose. UUIDs can serve as non-secret resource identifiers alongside separate secret tokens.
For a broader discussion of how randomness and entropy apply to security, see our article on password security: why length beats complexity.
Generating UUIDs
Our UUID generator creates version 4 UUIDs using a cryptographically secure random number generator. Each generated UUID has 122 bits of randomness, is formatted in the standard 8-4-4-4-12 hyphenated representation, and is ready to use as a database key, API identifier, or any other context that needs a unique label.
For converting between the hexadecimal representation of UUID bytes and decimal values, our hex-decimal converter handles the translation. And for computing deterministic hashes (which is conceptually related to how UUID v3 and v5 work), our SHA-256 hash generator demonstrates the hashing approach.
The Bottom Line
UUIDs solve a fundamental problem in distributed systems: generating globally unique identifiers without central coordination. Version 4, based on pure randomness, has been the default for over a decade and remains a solid choice when time-ordering doesn't matter. Version 7, standardized in RFC 9562 in 2024, adds millisecond-precision timestamps that provide chronological sorting — solving the B-tree performance problem that made v4 costly as a database primary key. The collision probability for both versions is vanishingly small at any realistic scale, provided the random number generator is cryptographically sound. Choose v7 for new database-backed applications, v4 when you need no temporal information in the ID, and v5 when you need deterministic IDs derived from names. Our UUID generator gets you started immediately.
References
RFC 9562 — Universally Unique IDentifiers (UUIDs) — The 2024 specification replacing RFC 4122, introducing UUID versions 6, 7, and 8.
Wikipedia — Universally Unique Identifier — Comprehensive overview of UUID history, versions, and collision analysis.
GUID Generator — UUID Versions Guide — Practical comparison of all UUID versions with use-case recommendations.
GUID Generator — UUIDs in Databases — Performance, indexing, and storage guidance for UUID primary keys.
Wikipedia — Birthday Problem — The probability theory behind UUID collision calculations.