Developer

What Is a UUID? Versions, Uses, and How to Generate One

HR
Hassaan Rasheed
· August 23, 2026 10 min read

A developer's terminal showing multiple UUID4 strings printed as output from a generation command, with a code editor open behind it displaying a uuid function call in JavaScript, and the UUID generator tool visible in a browser tab showing a freshly generated identifier in the standard 8-4-4-4-12 hex format

You see them everywhere once you start looking: in database rows, API responses, log files, file names, browser storage. They look like 550e8400-e29b-41d4-a716-446655440000. You know they are identifiers, but not why they are formatted that way, what the different versions mean, or why most applications generate one version and almost never touch the others.

The UUID generator produces a version 4 UUID in one click, ready to copy. This guide covers what the format contains, how each version works, when to choose one over another, and the practical considerations for using UUIDs in databases and APIs.

What Is a UUID?

A UUID (Universally Unique Identifier) is a 128-bit value. Those 128 bits are represented as 32 hexadecimal digits arranged in a fixed pattern: five groups separated by hyphens in an 8-4-4-4-12 structure. The example from RFC 4122 itself:

550e8400-e29b-41d4-a716-446655440000

The design goal is coordination-free uniqueness. Any machine, at any time, can generate a UUID without registering with a central authority, and the result will be unique across all machines and all time. This is what makes UUIDs practical for distributed systems: generating a new record ID does not require a database round-trip to get the next sequence value.

RFC 4122, published by the IETF in 2005, defines the format, the five version types, and the bit-level layout. A follow-up standard, RFC 9562, published in 2024, added UUID versions 6, 7, and 8 and explicitly defined the nil and max UUIDs. Most current systems implement RFC 4122 versions, though UUID7 is gaining adoption for its time-sortable property.

The Five UUID Versions

RFC 4122 defines five UUID versions. Every version uses the same 128-bit output format but generates the value differently.

VersionGeneration BasisDeterministic?Privacy-safe?Primary Use
v1Timestamp + MAC addressNoNoLegacy systems, time-ordered IDs
v2Timestamp + POSIX UIDNoNoDCE Security (rarely used)
v3MD5(namespace + name)YesYesNamespace hashing, legacy
v4Random dataNoYesGeneral use (dominant choice)
v5SHA-1(namespace + name)YesYesNamespace hashing, preferred

Version 2 appears in older distributed computing contexts (specifically DCE/RPC systems) and is rarely seen in modern application development. The practical decision for new applications is between v1, v4, and v5.

Why Version 4 Is the Standard Choice

Version 4 UUIDs are random. The generator takes 122 bits of random data and sets the remaining 6 bits to the version marker (4) and variant marker (RFC 4122 variant) specified by the standard. That is the entire process. No clock. No network interface lookup. No coordination with other processes.

The 6 bits reserved for markers are where a common misconception lives. A UUID4 has 128 bits total but only 122 bits of actual randomness. Looking at the pattern:

xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
             ^ always 4 (version)
                  ^ always 8, 9, a, or b (variant)

Every position marked x is genuinely random. The version digit in position 13 of the hex string is always 4. The first hex digit of the fourth group is always 8, 9, a, or b because those four values encode the RFC 4122 variant in binary (10xx). Every other digit is random.

This simplicity is why v4 dominates. Standard libraries handle it with a single call: crypto.randomUUID() in Node.js 14.17+ and modern browsers, uuid.uuid4() in Python, uuid.New() in Go. Frameworks that need a unique identifier for any purpose (session tokens, record IDs, idempotency keys) reach for UUID4 without a second thought.

What Is the Difference Between a UUID and a GUID?

UUID and GUID are the same thing. GUID (Globally Unique Identifier) is Microsoft's term, used throughout Windows, COM, OLE, and .NET documentation. UUID is the IETF term from RFC 4122. The format, the version structure, and the byte layout are identical.

Microsoft's CoCreateGuid() function in Windows produces RFC 4122-compatible output. When GUIDs appear in Windows-style documentation surrounded by curly braces, like {550e8400-e29b-41d4-a716-446655440000}, the braces are a display convention for the Windows registry and COM interfaces. The braces are not part of the value itself and should be stripped when using the ID in a database or API.

The terms appear in the same codebases when teams mix Windows-origin components with cross-platform code. Treating them as interchangeable is correct.

How Low Is the Collision Risk?

Generating 1 billion version 4 UUIDs per second continuously would require approximately 85 years before the probability of any two UUIDs matching reached 50%. The space has 2^122 possible values, roughly 5.3 × 10^36. The birthday problem says collision probability grows with the square root of the number of items relative to the space size. Applied to 2^122, the number of UUIDs needed to reach 50% collision probability is approximately 2.7 × 10^18.

In practical terms: a system generating 1 million UUIDs per day would need 7.4 trillion years to accumulate enough UUIDs for a 50% collision chance. The age of the universe is about 14 billion years.

This is why production systems do not build collision detection into UUID generation. The actual risk of a UUID collision in any real application is many orders of magnitude lower than the risk of a disk write failure silently corrupting the same data. Teams that add uniqueness constraints on UUID columns do so for foreign key integrity guarantees, not because they expect collisions.

When to Use Version 5 Instead of Version 4

Version 5 is deterministic: given the same namespace UUID and the same name string, it always produces the same output UUID. The generation process concatenates the namespace bytes and the name bytes, hashes them with SHA-1, then truncates and formats the result as a 128-bit UUID with the version 5 marker.

The use case is stable identifiers for named resources. If admin@example.com should always have the same user UUID whether the ID is generated today, next year, or on a different server, use UUID5 with a fixed namespace UUID and the email address as the name. Any system that knows the namespace and the name can independently compute the same UUID without querying a database.

RFC 4122 defines standard namespace UUIDs for DNS names, URLs, ISO OIDs, and X.500 names. You can also generate your own namespace UUID once (using UUID4) and treat it as a permanent constant for your application.

Version 3 does the same thing with MD5 instead of SHA-1. Since MD5 is cryptographically broken, prefer version 5 for any new code. The determinism property is identical; only the hash function differs.

The Nil UUID and Max UUID

The nil UUID is all zeros: 00000000-0000-0000-0000-000000000000. RFC 4122 defines it as the UUID representing the absence of a UUID, used the same way null represents the absence of a value in most type systems. Some APIs return the nil UUID when a query finds no matching resource rather than returning null or an error response.

RFC 9562 (2024) explicitly defines the max UUID as all F's: ffffffff-ffff-ffff-ffff-ffffffffffff. It is used as a sentinel value in range queries, similar to how INT_MAX is used in numeric contexts.

RFC 9562 also defines UUID version 7, which was absent from RFC 4122. Version 7 encodes a Unix millisecond timestamp in the most significant bits followed by random data in the remaining bits. This makes UUID7 values time-sortable: newer values are always lexicographically greater than older values. This property solves the B-tree fragmentation problem that UUID4 causes in database indexes.

How to Generate a UUID

Browser (no code required): Open the UUID generator and click Generate. The tool uses crypto.randomUUID() from the Web Crypto API, which draws entropy from hardware-level sources. No account, no installation.

JavaScript (browser and Node.js 14.17+):

const id = crypto.randomUUID();
// "550e8400-e29b-41d4-a716-446655440000"

Node.js with the uuid package (for older environments or v5 support):

import { v4 as uuidv4, v5 as uuidv5 } from 'uuid';

const id = uuidv4();
// Random UUID4

const stableId = uuidv5('admin@example.com', uuidv5.URL);
// Same UUID every time for the same email + namespace

Python:

import uuid

id = str(uuid.uuid4())
# "550e8400-e29b-41d4-a716-446655440000"

stable_id = str(uuid.uuid5(uuid.NAMESPACE_URL, 'admin@example.com'))
# Deterministic UUID5

PostgreSQL (13+):

SELECT gen_random_uuid();
-- Returns a UUID4

MySQL:

SELECT UUID();
-- Returns a UUID1 (timestamp-based, not random)

The MySQL UUID() function generates version 1, not version 4. Version 1 UUIDs embed the server's MAC address and a timestamp. If you use UUID() to generate primary keys in MySQL and privacy matters, be aware that these IDs reveal your database server's network interface address. Generate UUID4 values in your application layer and pass them to MySQL rather than relying on the database function.

A diagram showing the 128-bit UUID structure split into labeled segments: the 60-bit timestamp field in version 1, the 4-bit version field always set to the version number, the 2-bit variant field marking RFC 4122 compliance, and the remaining random bits shown in the UUID4 structure with the fixed character positions highlighted at the version and variant positions

UUID as a Database Primary Key

UUIDs work well as primary keys in distributed systems. Multiple application servers can insert rows simultaneously without coordinating on which ID to use next. Auto-increment integers require a single sequence source, which becomes a bottleneck under high concurrent write load or when merging records from separate databases.

The tradeoff is write performance on large tables. PostgreSQL and MySQL both use B-tree indexes by default. Sequential integers always append to the rightmost index page. Random UUID4 values insert at arbitrary positions throughout the index, causing frequent page splits and rebalancing. On tables with tens of millions of rows, this fragmentation slows write operations measurably.

The practical solutions: use UUID7 (time-sortable, no fragmentation), use PostgreSQL's native uuid column type with the uuid-ossp extension's uuid_generate_v1mc() function (which generates a version 1 UUID with a random node ID instead of the actual MAC address, giving you time-sortable values without the privacy issue), or maintain sequential integer primary keys internally and expose application-layer UUIDs for external API responses. A 36-character UUID string can also be stored as 24-character base64 in space-constrained contexts using the base64 encoder and decoder.

Storing and Validating UUIDs

UUIDs are commonly stored as 36-character strings (VARCHAR(36) including hyphens). PostgreSQL has a native uuid column type that stores 16 bytes internally while accepting and returning the standard string format. This type validates format automatically and indexes efficiently. MySQL lacks a native UUID type but accepts BINARY(16) with manual conversion, saving half the storage compared to text.

To validate a UUID string format (not uniqueness, just well-formedness), a standard regex works across languages:

^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$

This matches any RFC 4122 UUID v1 through v5 in lowercase. UUIDs are case-insensitive by specification: 550E8400 and 550e8400 identify the same value. The convention is lowercase, but APIs that return uppercase UUIDs are fully RFC-compliant.

When building test data that includes UUIDs, the fake data for testing guide covers how to generate realistic-looking test datasets where UUIDs appear in the expected format alongside other fields. The hash generator handles cases where you need a one-way fingerprint of data rather than a unique identifier. Both UUIDs and hashes appear as fixed-length hex strings in developer workflows but serve entirely different purposes.

The developer tools section has the UUID generator alongside the base64 encoder, hash generator, and other utilities for common development tasks.

Frequently Asked Questions

A UUID (Universally Unique Identifier) is a 128-bit identifier formatted as 32 hexadecimal digits in five groups separated by hyphens: 8-4-4-4-12. Example: 550e8400-e29b-41d4-a716-446655440000. UUIDs can be generated independently on any machine without a central registry, and the probability of two UUIDs matching is low enough that production systems treat collision as impossible. The format is defined by RFC 4122, published by the IETF in 2005.

Version 1 generates a UUID from the current timestamp and the network MAC address of the generating machine, making it time-sortable but not privacy-safe. Version 3 uses MD5 to hash a namespace UUID and a name string into a deterministic UUID. Version 4 uses 122 bits of random data and is the most widely used version. Version 5 does the same as version 3 but uses SHA-1 instead of MD5. Version 2 (DCE Security) appears in older operating system contexts and is rarely used in new applications.

Version 4 requires no network access, no timestamp synchronization, and no shared state between generators. Any process can produce a valid UUID4 from random data alone. The 122 bits of entropy (the other 6 bits encode version and variant markers required by RFC 4122) produce approximately 5.3 × 10^36 possible values. Standard libraries expose it as a single function call: crypto.randomUUID() in Node and modern browsers, uuid.uuid4() in Python, uuid.New() in Go.

UUID and GUID refer to the same thing. GUID stands for Globally Unique Identifier and is the term Microsoft uses in Windows, COM, and .NET documentation. UUID is the term from RFC 4122. The structure is identical: 128 bits, 32 hex digits, 8-4-4-4-12 grouping, same five version types. Microsoft's CoCreateGuid() function produces RFC 4122-compatible output. When GUIDs appear in Windows contexts surrounded by curly braces ({550e8400-...}), the braces are a display convention, not part of the value.

For version 4 UUIDs, generating 1 billion per second continuously would require approximately 85 years before the probability of any two matching reached 50%. The working space is 2^122 possible values (about 5.3 × 10^36). In practice, UUID collision probability is lower than the probability of undetected hardware memory corruption in the same time period. This is why production systems do not add uniqueness constraints on UUID primary keys for collision prevention; they add them only for foreign key integrity.

Use version 5 when you need the same UUID for the same named resource every time. Given a fixed namespace UUID and a name string, version 5 always produces the same output without any storage or communication required between systems. This works for stable identifiers tied to known resources: email addresses, URLs, product SKUs. Use version 4 when each ID must be unique and unpredictable. Version 3 does the same as version 5 but uses MD5, which is cryptographically weak — prefer version 5 for new code.

Yes, with a performance caveat. UUID primary keys work well in distributed systems where multiple servers insert rows without coordinating on ID assignment. The tradeoff is index fragmentation: version 4 UUIDs insert in random order, causing B-tree index pages to split and rebalance frequently on large tables. Solutions include UUID version 7 (time-sortable, defined in RFC 9562), PostgreSQL's native uuid column type, or keeping integer primary keys internally while exposing UUIDs through an application mapping layer.

HR

Written by

Hassaan Rasheed

Builder of ToolCenterHub. Passionate about creating fast, privacy-first tools that anyone can use without friction, accounts, or paywalls. Writing about design, development, and the web.

Connect on LinkedIn