What Is a UUID? The Complete Guide to Unique Identifiers
On this page
A comprehensive guide to understanding Universally Unique Identifiers (UUIDs), their mathematical foundation, the differences between versions 1 to 8, database storage options, and development best practices.
If you have ever seen a string like 550e8400-e29b-41d4-a716-446655440000 in a database row, an API response, or a log file and wondered what it means, you have met a UUID. UUIDs are one of the most widely used building blocks in modern software, yet they are often misunderstood. This guide explains exactly what a UUID is, how it works under the hood, the differences between every version (v1 through v8), and how to use them correctly in real systems.
Whether you are a beginner trying to understand the term or an experienced engineer choosing an identifier strategy for a distributed system, this article covers the practical details that actually matter, complete with examples, diagrams, code in seven languages, and battle-tested best practices.
A UUID (Universally Unique Identifier) is a 128-bit value used to uniquely identify information without a central authority. It is written as 36 characters in an 8-4-4-4-12 hexadecimal pattern, such as 550e8400-e29b-41d4-a716-446655440000. Because any machine can generate one independently with a near-zero chance of collision, UUIDs are ideal for distributed systems, databases, and APIs.
- 01A UUID is a 128-bit identifier standardized by RFC 9562 (which replaced RFC 4122 in 2024).
- 02It is globally unique by construction, so no coordination or central server is required.
- 03Version 4 (random) is the most common; version 7 (time-ordered) is the modern choice for database keys.
- 04Store UUIDs as 16 binary bytes, not 36-character strings, for better performance.
- 05UUIDs are identifiers, not secrets, and collisions are practically impossible.
What Is a UUID?
A UUID (Universally Unique Identifier) is a 128-bit number used to identify information in computer systems. In practice, it is almost always displayed as a 36-character string of hexadecimal digits grouped into five blocks separated by hyphens:
550e8400-e29b-41d4-a716-446655440000
8 4 4 4 12 (hex digits per group)
The defining property of a UUID is right there in the name: it is universally unique. Two correctly generated UUIDs are, for all practical purposes, guaranteed to be different from every other UUID ever created, anywhere in the world, on any machine. This uniqueness does not come from a central registry or a coordinating server. Instead, it comes from mathematics: the value is large enough (128 bits is about 340 undecillion possible values) that the probability of two generators ever producing the same one is vanishingly small.
UUIDs were originally standardized in RFC 4122 (2005) and were significantly modernized by RFC 9562 in May 2024, which added the time-ordered versions 6, 7, and 8 that are reshaping how databases use UUIDs today.
You can generate UUIDs instantly in your browser with our UUID Generator to see the format in action.
What Does UUID Stand For?
UUID stands for Universally Unique Identifier. You will also frequently see the term GUID, which stands for Globally Unique Identifier. These are two names for the same thing:
- UUID is the term used by the IETF standards (RFC 4122 / RFC 9562) and by most open-source ecosystems.
- GUID is Microsoft’s name for the identical 128-bit value, used across Windows, .NET, SQL Server, and COM.
The “universally” versus “globally” distinction is purely historical naming. There is no technical difference in the value itself. If you need to create one in a Microsoft context, our GUID Generator produces values that are fully interchangeable with UUIDs.
Why Are UUIDs Used?
The single biggest reason to use UUIDs is decentralized, coordination-free uniqueness. With a traditional auto-increment integer, a central database must hand out each new ID so that no two rows clash. That works fine for a single database, but it breaks down the moment you have multiple services, multiple databases, offline clients, or data that needs to be merged later.
With UUIDs, any node can mint a brand-new identifier locally, instantly, and be confident it will not collide with one created by any other node.
Beyond decentralization, UUIDs are popular because they:
- Enable client-side ID generation. A mobile app or browser can create a record’s ID before it ever reaches the server, simplifying optimistic UI and offline-first apps.
- Make data merging safe. Records from different shards, databases, or tenants can be combined without primary-key collisions.
- Avoid leaking business metrics. Sequential IDs like
/orders/1042reveal how many orders you have; a UUID does not. - Decouple services. Microservices can reference each other’s entities without a shared sequence generator.
- Simplify replication and sharding. Each shard generates keys independently, with no central bottleneck.
How Does a UUID Work?
A UUID works by combining a large value space with version-specific generation rules so that the result is unique without coordination. There are two broad strategies depending on the version:
- Randomness (version 4). Fill almost all of the 128 bits with cryptographically secure random data. With 122 random bits, the odds of ever producing the same value twice are astronomically small.
- Time plus a node or randomness (versions 1, 6, 7). Combine a high-resolution timestamp with additional bits (a node identifier, a counter, or random data) so values are both unique and sortable by creation time.
- Hashing a name (versions 3 and 5). Deterministically derive the UUID from a namespace and a name using MD5 (v3) or SHA-1 (v5), so the same input always yields the same UUID.
Regardless of strategy, every UUID reserves a few specific bits to record its version (which algorithm created it) and its variant (which layout standard it follows). Those bits are what let any system look at a UUID and know how to interpret it. Let’s break down exactly where they live.
UUID Structure Explained
The canonical UUID string is 36 characters: 32 hexadecimal digits arranged in five groups of 8-4-4-4-12, joined by four hyphens. Two positions are special and are not random or time data at all: the version digit and the variant digit.

Reading the example 550e8400-e29b-41d4-a716-446655440000:
- The version is the first digit of the third group. Here it is
4, so this is a version 4 (random) UUID. - The variant is the first digit of the fourth group. Here it is
a, which (in binary1010) signals the standard RFC 9562 variant. Valid variant digits for this layout are8,9,a, orb.
In raw binary, the 128 bits are laid out as 16 bytes:
| Field | Bits | Purpose |
|---|---|---|
time_low | 32 | Low part of timestamp (or random in v4) |
time_mid | 16 | Middle part of timestamp (or random) |
version + time_hi | 16 | 4 version bits + remaining time/random |
variant + clock_seq | 16 | 2-3 variant bits + clock sequence/random |
node | 48 | MAC address, random, or remaining data |
UUID Length Explained
A common point of confusion is “how long is a UUID?” The answer depends on representation:
- Bits: 128
- Bytes (binary): 16
- Canonical string: 36 characters (32 hex digits + 4 hyphens)
- String without hyphens: 32 characters
- As a URN: 45 characters (
urn:uuid:prefix + 36)
This distinction matters enormously for databases. Storing the 36-character string in a VARCHAR(36) column uses more than twice the space of the 16-byte binary form and produces slower, larger indexes, a point we return to in the database section.
UUID Versions Explained
There are several UUID versions, each defined by how it fills those 128 bits. The versions evolved over two decades, from the original timestamp-based v1 to the modern, database-friendly v7.
- v1Timestamp + MACRFC 4122 (2005)
- v2DCE SecurityRarely used
- v3MD5 namespaceDeterministic
- v4RandomMost common
- v5SHA-1 namespaceDeterministic
- v6Ordered timeRFC 9562 (2024)
- v7Unix time + randomModern DB keys
UUID Version 1: Timestamp and Node
Version 1 combines a 60-bit timestamp (100-nanosecond intervals since October 15, 1582), a clock sequence, and a 48-bit node identifier, traditionally the machine’s MAC address. It is sortable-ish but leaks the MAC address and creation time, which is a privacy and security concern.
UUID Version 2: DCE Security
Version 2 is a rarely used variant for DCE (Distributed Computing Environment) that embeds a POSIX UID/GID. You will almost never need it.
UUID Version 3 and Version 5: Name-Based (Deterministic)
Versions 3 and 5 are deterministic: they hash a namespace UUID plus a name to produce the result. The same input always yields the same UUID. Version 3 uses MD5; version 5 uses SHA-1 and is preferred. These are perfect for generating a stable ID from a known value, such as a URL or username.
import uuid
# Same input always produces the same UUID
uuid.uuid5(uuid.NAMESPACE_DNS, "example.com")
# => 'cfbff0d1-9375-5685-968c-48ce8b15ae17'
UUID Version 4: Random
Version 4 is the workhorse. It fills 122 bits with cryptographically secure random data (the other 6 bits are fixed version and variant markers). It carries no timestamp, no MAC address, and no structure, which makes it private and simple, but not sortable. This is the default in most languages and the right choice for API keys, tokens, and general-purpose IDs. Try it with our UUID v4 generator.
UUID Version 6: Reordered Timestamp
Version 6 takes the v1 fields and reorders them so the most significant timestamp bits come first. This makes v6 UUIDs sort chronologically as plain byte strings while staying field-compatible with v1 systems. Generate one with the UUID v6 generator.
UUID Version 7: Unix Timestamp and Random
Version 7 is the star of RFC 9562 and the recommended choice for database primary keys. It starts with a 48-bit Unix millisecond timestamp followed by random bits. The result is time-sortable (great for B-tree indexes), still effectively collision-free, and does not leak a MAC address. Generate one with the UUID v7 generator.
UUID Version 8: Custom
Version 8 is an intentionally open, vendor-specific format. As long as you set the version and variant bits correctly, the remaining 122 bits are yours to define for experimental or specialized use cases.
| Version | Basis | Sortable | Deterministic | Best for |
|---|---|---|---|---|
| v1 | Time + MAC | Partially | No | Legacy systems |
| v3 | MD5(namespace, name) | No | Yes | Stable IDs from names |
| v4 | Random | No | No | General purpose, tokens |
| v5 | SHA-1(namespace, name) | No | Yes | Stable IDs from names |
| v6 | Reordered time + node | Yes | No | v1 migration, ordered keys |
| v7 | Unix ms + random | Yes | No | Modern database keys |
| v8 | Custom | Depends | Depends | Experimental/vendor |
Which UUID Version Should You Use?
For the overwhelming majority of new projects, the answer is simple: use v7 for database keys and v4 for everything else. The decision tree below walks through the edge cases.
If your language or database does not yet support v7 natively, you can pull it in through a small library (covered below) or fall back to v4. Avoid v1 in new systems because of the MAC-address leakage.
UUID vs Other Identifiers
UUID is not the only identifier scheme. Here is how it stacks up against the alternatives you are most likely to consider. You can also explore these side by side on our comparison page.
UUID vs GUID
As covered above, these are the same 128-bit value. UUID is the IETF/open-source term; GUID is Microsoft’s. The only practical differences are cosmetic: Microsoft tooling sometimes wraps the value in braces ({550e8400-...}) and historically stored the first three fields in little-endian byte order.
| Aspect | UUID | GUID |
|---|---|---|
| Size | 128-bit | 128-bit |
| Standard | RFC 9562 | Microsoft (RFC-compatible) |
| Formatting | Plain hyphenated | Sometimes brace-wrapped |
| Ecosystem | Cross-platform | Windows / .NET |
UUID vs Auto-Increment ID
| Aspect | UUID | Auto-Increment |
|---|---|---|
| Size | 16 bytes | 4-8 bytes |
| Generation | Any node, no coordination | Central database only |
| Ordering | Only v6/v7 | Always sequential |
| Leaks row count | No | Yes |
| Merge/shard safe | Yes | No (collisions) |
| Index performance | v7 good, v4 poor | Excellent |
Use auto-increment when you have a single database, value the smallest possible keys, and do not need distributed generation. Use UUIDs when you need decentralization, client-side IDs, or merge-safety.
UUID vs ULID
ULID (Universally Unique Lexicographically Sortable Identifier) is also 128-bit but encodes as 26 Base32 characters and is sortable by default. UUID v7 closes most of the gap that originally made ULID attractive, while keeping the standardized, widely supported UUID format. Compare them with our ULID generator.
| Aspect | UUID v7 | ULID |
|---|---|---|
| Bits | 128 | 128 |
| Text length | 36 chars | 26 chars |
| Encoding | Hex | Crockford Base32 |
| Sortable | Yes | Yes |
| Standardized | RFC 9562 | Community spec |
UUID vs NanoID
NanoID produces compact, URL-friendly random strings (21 characters by default) and is popular for public-facing short IDs. It is not a UUID and carries no version/variant structure, but it is excellent when you want shorter, opaque IDs in URLs.
UUID vs Random String
A hand-rolled “random string” (for example, Base64 of some random bytes) can work, but UUIDs give you a standard format, a known collision profile, built-in version metadata, and broad library and database support. For ad-hoc tokens you can use our Password Generator or Base64 Encoder, but for identifiers a UUID is usually the better-defined choice.
UUID Examples and Format Validation
Here are valid UUID examples across versions so you can recognize them in the wild:
v1 6ba7b810-9dad-11d1-80b4-00c04fd430c8
v3 3d813cbb-47fb-32ba-91df-831e1593ac29
v4 550e8400-e29b-41d4-a716-446655440000
v5 cfbff0d1-9375-5685-968c-48ce8b15ae17
v7 018f8c5e-7b3a-7c1d-9a2b-3f4e5d6c7b8a
nil 00000000-0000-0000-0000-000000000000
The all-zero value is the special nil UUID, and the all-F value is the max UUID, both defined by the spec as sentinels.
Validating a UUID
To validate the canonical format, check the length, the hyphen positions, the hex digits, and the version/variant constraints. A robust regular expression looks like this:
const UUID_RE =
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
UUID_RE.test("550e8400-e29b-41d4-a716-446655440000"); // true
UUID_RE.test("not-a-uuid"); // false
The [1-8] group restricts the version digit to the defined versions, and [89ab] restricts the variant digit to the RFC 9562 variant. If you only need a loose check, you can relax those two character classes to [0-9a-f].
Can UUIDs Collide?
Technically yes; practically no. A collision means two independently generated UUIDs turn out identical. For version 4, 122 bits are random, giving about 5.3 x 10^36 possible values.
The practical caveat: collision math assumes a good random source. The fastest way to cause real collisions is to use a weak or improperly seeded random number generator, which brings us to security.
Are UUIDs Secure?
The most important mental model is this: a UUID is an identifier, not a secret. Keep three rules in mind:
- Use a CSPRNG for v4. Generate randomness with a cryptographically secure source (
crypto.randomUUID(),crypto.getRandomValues(),os.urandom). Never useMath.random(), which is predictable and not collision-safe. - Do not treat a UUID as authorization. A v4 UUID is hard to guess, but if it appears in URLs, logs, or referrers it can leak. Pair it with real access control. For inspecting tokens that do carry auth claims, use our JWT Decoder.
- Avoid v1 where privacy matters. Version 1 can embed the generating machine’s MAC address and a precise timestamp, which is sensitive metadata.
Generating “UUIDs” with Math.random() produces low-entropy, predictable values that can collide and be guessed. Always use crypto.randomUUID() or a vetted library instead.
How to Generate UUIDs in Any Language
Almost every language ships UUID support in the standard library or a one-line dependency. Below are idiomatic snippets. For deeper, language-specific walkthroughs, see the Developer Lab.
UUID Generation in JavaScript
In any modern browser (in a secure context) the Web Crypto API gives you v4 UUIDs with zero dependencies:
const id = crypto.randomUUID();
// => "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed"
See more in the JavaScript UUID guide.
UUID Generation in Node.js
crypto.randomUUID() is built in from Node.js 16 (and 14.17+). For v7 or v5, add the uuid package:
import { randomUUID } from 'node:crypto';
import { v7 as uuidv7 } from 'uuid';
randomUUID(); // v4, no dependency
uuidv7(); // time-ordered v7
See the Node.js UUID guide.
UUID Generation in Python
Python’s standard uuid module covers v1, v3, v4, and v5 out of the box:
import uuid
uuid.uuid4() # random v4
uuid.uuid5(uuid.NAMESPACE_URL, "https://example.com") # deterministic
# For v7, use a library such as uuid6 or uuid-utils
See the Python UUID guide.
UUID Generation in Java
java.util.UUID generates v4 (and v3) directly. For v7, use a library like java-uuid-generator (JUG):
import java.util.UUID;
UUID id = UUID.randomUUID(); // version 4
String s = id.toString();
See the Java UUID guide.
UUID Generation in PHP
PHP has no built-in UUID type, but the ramsey/uuid library is the de facto standard:
use Ramsey\Uuid\Uuid;
$v4 = Uuid::uuid4()->toString();
$v7 = Uuid::uuid7()->toString(); // ramsey/uuid 4.7+
See the PHP UUID guide.
UUID Generation in Go
The widely used github.com/google/uuid package generates v4 by default:
import "github.com/google/uuid"
id := uuid.New().String() // v4
v7, _ := uuid.NewV7() // time-ordered v7
See the Go UUID guide.
UUID Generation in C#
.NET has Guid.NewGuid() for v4, and .NET 9 added native v7:
Guid v4 = Guid.NewGuid(); // version 4
Guid v7 = Guid.CreateVersion7(); // .NET 9+
string s = v4.ToString();
See the C# UUID guide.
UUIDs in Databases and Indexing Performance
This is where UUID choices have the biggest real-world impact. The problem with random v4 UUIDs as primary keys is insert locality. Most databases store rows in a B-tree ordered by the primary key. Sequential keys append neatly to the end of the tree; random keys scatter writes across the whole tree, causing page splits, cache misses, and index fragmentation.
Storage Overhead: String vs Binary
How you store a UUID matters as much as which version you pick. The canonical 36-character string is convenient but wasteful. Storing the raw 16 bytes cuts storage by more than half and shrinks every index that references the key.
In PostgreSQL, use the native uuid type and gen_random_uuid():
CREATE TABLE users (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
email text NOT NULL
);
In MySQL 8, store as BINARY(16) and convert with UUID_TO_BIN(). The optional second argument reorders the time bytes so values sort better in the index:
CREATE TABLE users (
id BINARY(16) PRIMARY KEY,
email VARCHAR(255) NOT NULL
);
INSERT INTO users (id, email)
VALUES (UUID_TO_BIN(UUID(), 1), 'a@example.com');
To inspect or convert Unix timestamps embedded in v7 UUIDs, our Timestamp Converter is handy.
| Practice | Impact |
|---|---|
| Use v7 instead of v4 for keys | Faster inserts, less fragmentation |
| Store as 16-byte binary | ~55% less storage, smaller indexes |
| Avoid UUID as clustered key in some engines | Prevents secondary-index bloat |
| Keep a separate sequential surrogate if needed | Best of both worlds for some schemas |
UUID Best Practices
- Pick the right version. v7 for keys, v4 for tokens, v5 for deterministic IDs. Avoid v1 in new code.
- Generate with a CSPRNG. Use
crypto.randomUUID()or a vetted library, neverMath.random(). - Store as binary. Use the native
uuidtype orBINARY(16), notVARCHAR(36). - Normalize to lowercase. The spec is case-insensitive on input, but store and compare a single canonical case.
- Validate at boundaries. Use a regex or library check on any UUID arriving from a client or external system.
- Do not parse meaning out of v4. It is pure randomness; only v1/v6/v7 carry a timestamp.
- Index thoughtfully. Prefer time-ordered keys for high write throughput.
- Treat UUIDs as identifiers, not secrets. Add real authorization on top.
Common UUID Mistakes
- Using
Math.random()to “make a UUID.” It is neither unique enough nor secure. - Storing as
VARCHAR(36)and wondering why indexes are huge and slow. - Using random v4 as a high-volume primary key and hitting write amplification; switch to v7.
- Assuming v4 is sortable. It is not; only the timestamp-based versions are.
- Exposing v1 UUIDs publicly and unintentionally leaking MAC address and creation time.
- Treating a UUID in a URL as access control. Guessability is not authorization.
- Mixing cases so that string comparisons fail across systems.
When Should You Not Use UUIDs?
UUIDs are powerful, but they are not always the right tool:
- Small, single-database apps where a 4-8 byte auto-increment integer is simpler and faster.
- Public-facing short links or codes where 36 characters are too long; consider NanoID or a short hash.
- Extremely storage- or bandwidth-constrained systems (embedded, high-frequency telemetry) where 16 bytes per ID is too much.
- Human-typed identifiers like coupon or invite codes, where a shorter, friendlier format is better.
- When you need monotonic, gap-free sequences (for example, legally required invoice numbering). UUIDs are not sequential counters.
Frequently Asked Questions
What is a UUID?
A UUID (Universally Unique Identifier) is a 128-bit value used to uniquely label information in computer systems. It is written as 36 characters in the 8-4-4-4-12 hexadecimal format, such as 550e8400-e29b-41d4-a716-446655440000, and can be generated independently on any machine without a central authority.
What does UUID stand for?
UUID stands for Universally Unique Identifier. Microsoft’s equivalent term is GUID (Globally Unique Identifier); both describe the same 128-bit value.
Is a UUID the same as a GUID?
Yes. UUID and GUID refer to the same 128-bit identifier defined by RFC 9562. UUID is the standards term; GUID is Microsoft’s name. The only differences are formatting conventions.
Which UUID version should I use?
Use v7 for database primary keys (time-sortable and index-friendly), v4 for general-purpose random IDs such as API keys and sessions, and v5 for deterministic IDs derived from a name or namespace.
Can two UUIDs ever be the same?
A collision is theoretically possible but practically negligible for v4, which has 122 random bits. You would need to generate about one billion UUIDs per second for roughly 85 years to reach a 50% chance of a single duplicate.
Are UUIDs secure?
UUIDs are identifiers, not secrets. A v4 UUID from a secure random source is hard to guess, but should not be your only access control. Avoid v1 where privacy matters, since it can embed a MAC address and timestamp.
How long is a UUID?
A UUID is 128 bits: 16 bytes in binary, or 36 characters as a canonical string (32 hex digits plus 4 hyphens).
How do I generate a UUID in JavaScript?
Call crypto.randomUUID() in any modern browser secure context or in Node.js 16+. It returns an RFC-compliant v4 UUID with no dependencies.
Are UUIDs bad for database performance?
Random v4 UUIDs can slow inserts and bloat indexes because they are unordered. Time-ordered v7 UUIDs avoid most of this, and storing UUIDs as 16-byte binary further improves efficiency.
What is the difference between a UUID and an auto-increment ID?
Auto-increment IDs are small sequential integers from a single database; UUIDs are 128-bit values any service can generate independently. UUIDs avoid coordination and do not leak row counts, but they are larger and, unless you use v7, not naturally ordered.
Conclusion
A UUID is a simple idea with deep practical value: a 128-bit identifier that any system can generate independently, with effectively zero chance of collision and no central coordinator. Understanding the versions, especially the difference between random v4 and time-ordered v7, lets you make the right call for tokens, keys, and distributed data.
The short version to remember: use v7 for database keys, v4 for general identifiers, store them as 16-byte binary, generate them with a secure random source, and treat them as identifiers rather than secrets. Follow those rules and UUIDs will serve you reliably from a single app to a globally distributed system.
Ready to put this into practice? Generate UUIDs instantly with our free UUID Generator, or compare formats side by side on the comparison page.
satyam
Infrastructure architect and distributed systems engineer focused on high-throughput identifier systems and practical developer tooling.