How UUIDs Work — Structure, Versions, and Collision Math
The anatomy of a UUID, what each version means, how randomness fills 128 bits, and why collisions are theoretical but validation still matters.
By Vertex Solutions Editorial
Someone pasted 550e8400-e29b-41d4-a716-446655440000 into Slack and asked if it was "random enough for lottery numbers." It wasn't random enough for that — nothing is, really — but it was a perfectly fine identifier for their staging database.
UUIDs look like random hex soup. Under the hood, they're structured data with version bits, variant bits, and rules that date back to the 1980s. Understanding that structure helps you validate inputs, pick the right version, and stop treating them as magic strings.
Quick answer
Someone pasted 550e8400-e29b-41d4-a716-446655440000 into Slack and asked if it was "random enough for lottery numbers." It wasn't random enough for that — nothing is, really — but it was a perfectly fine identifier for their staging database.
What a UUID actually is
A Universally Unique Identifier is a 128-bit value. Written in canonical form:
550e8400-e29b-41d4-a716-446655440000
|______|___|___|___|____________|
8 4 4 4 12 hex digits
That's 32 hexadecimal characters (0–9, a–f) in five groups separated by hyphens. Case doesn't matter for parsing — lowercase is a common API convention.
128 bits means 2^128 possible values. That's roughly 340 undecillion combinations. You will not exhaust the space in your career.
Generate samples with UUID Generator and notice how each refresh produces a completely different string.
The bit layout: version and variant
Not every bit is random. The UUID standard reserves specific positions:
Version — 4 bits at a fixed position identify how the UUID was generated (v1, v4, v7, etc.)
Variant — bits indicating which UUID specification family this follows (the common RFC 4122 variant sets particular bits to 10)
When you read a UUID like e29b-41d4-a716, the third group's first digit (4 in 41d4) often hints at version 4 — though always parse formally rather than eyeballing.
This structure lets validators reject garbage strings before hitting the database.
UUID versions you'll actually see
Version 1 — timestamp + MAC address
Version 1 combines:
- A 60-bit timestamp (100-nanosecond intervals since UUID epoch)
- A clock sequence for uniqueness within the same timestamp
- A node ID (historically MAC address; often randomized now for privacy)
Pros: Roughly time-ordered, no central coordinator needed
Cons: Can leak hardware info if real MACs are used; clock rollback edge cases
Version 4 — random
Version 4 sets the version bits to 0100 and fills the remaining bits with random data (from a CSPRNG in production).
Pros: Simple, opaque, no hardware leakage
Cons: Random ordering can fragment database B-tree indexes at very large scale
This is the default most developers reach for. UUID in API development covers when to expose them in REST paths and how to index them.
Version 7 — time-ordered random
Version 7 (newer, increasingly supported) puts a Unix timestamp in the leading bits and fills the rest with randomness.
Pros: Sortable by creation time, better index locality than v4
Cons: Ecosystem support still catching up; libraries vary
If you're choosing today for a greenfield Postgres app, v7 deserves a look alongside v4.
Others (v3, v5) — name-based
Versions 3 and 5 generate deterministic UUIDs from a namespace UUID plus a name string, using MD5 (v3) or SHA-1 (v5). Same inputs always produce the same UUID.
Use when: You need stable IDs derived from content (DNS names, URLs) without storing a mapping table
Avoid when: You need unpredictability — deterministic UUIDs are guessable if the namespace and name are known
Collision probability: the birthday problem
"Unique" doesn't mean "impossible to duplicate." It means the probability is negligible.
For v4 UUIDs with quality randomness, collision risk before the heat death of the universe is not your operational concern. Database unique constraints and application validation exist anyway — not because collisions will happen, but because bugs happen:
- Hardcoded test UUIDs copied to production
- Clients sending malformed strings
- Integer IDs accidentally cast to UUID columns
Validate format with Regex Tester using a pattern like:
^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
Adjust the version nibble [1-5] if you only accept specific versions.
How generation works in practice
Language runtimes — crypto.randomUUID() in modern browsers and Node, uuid npm package, uuid_generate_v4() in databases
Database defaults — PostgreSQL gen_random_uuid(), MySQL UUID()
Manual tools — UUID Generator for fixtures, demos, and quick clipboard copies
The critical requirement: use a cryptographically secure random source in production. Math.random() is not sufficient for security-sensitive ID generation, though it's fine for throwaway test data.
Storage formats
UUIDs appear in multiple representations:
| Format | Example | Notes |
|--------|---------|-------|
| Canonical string | 550e8400-e29b-41d4-a716-446655440000 | API JSON, logs |
| Binary(16) | 16 raw bytes | Compact DB storage |
| URN | urn:uuid:550e8400-... | Some XML systems |
Store as native uuid type when your database supports it. VARCHAR works but wastes space and skips format enforcement.
UUIDs vs other ID schemes
| Scheme | Sortable | Size | Predictable | |--------|----------|------|-------------| | Auto-increment int | Yes | 4–8 bytes | Yes | | UUID v4 | No | 16 bytes | No | | UUID v7 | Roughly | 16 bytes | No | | ULID | Yes | 16 bytes | No | | Snowflake | Yes | 8 bytes | Partially |
UUIDs win when you need distributed generation without coordination. Integers win when you need compact sequential URLs and don't expose them publicly.
Common misconceptions
"UUIDs are guaranteed unique" — Guaranteed by probability, not physics. Treat them as unique; enforce with DB constraints.
"Shorter UUIDs are fine" — Truncating breaks interoperability. Use ULIDs or custom short codes if length matters.
"Uppercase vs lowercase matters" — Parsing is case-insensitive; pick one convention for display consistency.
"UUID in URL = secure" — Opaque ≠ authorized. Always check ownership server-side.
Serialization in JSON and APIs
JSON has no binary UUID type. APIs serialize UUIDs as strings:
{
"order_id": "550e8400-e29b-41d4-a716-446655440000",
"customer_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
}
Inspect responses with JSON Formatter. Consistent hyphenation prevents client cache key splits.
Encoding binary UUID bytes for transport is a different operation — see Understanding Base64 Encoding for how encoding differs from ID generation.
Testing with UUIDs
- Generate unique fixtures per test case, not one shared constant
- Test malformed input: wrong length, wrong version nibble, non-hex characters
- Test case insensitivity in parsers
- Verify foreign key relationships survive UUID string round-trips
Related articles
- Using UUIDs in API Development — API design, indexing, and security patterns
- Understanding Base64 Encoding — encoding vs identifier generation
- Regex Debugging Tips — validating UUID format patterns
Related tools
- UUID Generator — Generate v4 UUIDs instantly
- Regex Tester — Test UUID validation patterns
- JSON Formatter — Inspect API responses with UUID fields
Key takeaways
- How many bits are in a UUID: 128 bits, usually displayed as 32 hexadecimal digits in five groups separated by hyphens (8-4-4-4-12 format).
- What is UUID version 4: Version 4 fills most bits with random data from a cryptographically secure or pseudo-random source, with version and variant bits fixed in standard positions.
- Can two UUIDs ever be the same: Theoretically yes, but the probability is astronomically low for v4 random UUIDs in any practical system.
Conclusion
A UUID is 128 bits with structure: version bits tell you how it was made, variant bits tell you which spec applies, and the remaining bits carry timestamp, randomness, or hashed name data depending on version. v4 random UUIDs power most modern systems; v7 is the rising alternative when sortability matters. Collisions won't keep you up at night — bad validation and missing auth checks might.
Frequently Asked Questions
Common questions answered to help you get the most from this tool.