DevBolt
·10 min read

Understanding UUIDs: Versions, Formats, and When to Use Each

FundamentalsDatabasesWeb Development

UUIDs (Universally Unique Identifiers) are 128-bit identifiers used everywhere — database primary keys, API request IDs, distributed systems, session tokens. This guide covers the different UUID versions, how they work, and when to pick each one.

What Is a UUID?

A UUID is a 128-bit number represented as 32 hexadecimal digits in five groups separated by hyphens:

UUID format
550e8400-e29b-41d4-a716-446655440000
\_____/ \__/ \__/ \__/ \__________/
  8       4    4    4       12

Total: 32 hex digits = 128 bits

The third group's first digit indicates the version. In the example above, 4 in 41d4 means UUID v4. The fourth group's first digit indicates the variant (usually 8, 9, a, or b for RFC 4122 UUIDs).

UUID vs GUID

They're the same thing. Microsoft calls them GUIDs (Globally Unique Identifiers), everyone else calls them UUIDs. The format, generation algorithms, and RFC specification are identical. If you see a GUID in .NET or SQL Server, treat it as a UUID.

UUID Versions Explained

UUID v1 — Timestamp + MAC Address

Combines a 60-bit timestamp (100-nanosecond intervals since October 15, 1582) with the machine's MAC address. UUIDs generated on the same machine sort chronologically.

UUID v1 structure
f47ac10b-58cc-1de5-97d0-0242ac120002
                  ^
                  version 1

Pros: Naturally sortable by time, guaranteed unique per machine
Cons: Leaks MAC address (privacy concern), clock skew issues

UUID v4 — Random

The most commonly used version. 122 bits are randomly generated (6 bits reserved for version and variant). No timestamp, no MAC address, no coordination needed.

UUID v4 structure
550e8400-e29b-41d4-a716-446655440000
                  ^
                  version 4

122 random bits → 2^122 possible values
≈ 5.3 × 10^36 unique UUIDs

Collision probability:
  • 1 billion UUIDs → ~0.00000000000000003% chance
  • You'd need to generate 2.71 × 10^18 UUIDs for a 50% chance

For most applications, v4 is the right choice. The collision probability is so low that it's effectively zero for any real-world use case.

UUID v7 — Timestamp + Random (Recommended)

The newest version (RFC 9562, 2024). Combines a 48-bit Unix timestamp (millisecond precision) with 74 random bits. This gives you the best of both worlds: natural sortability and privacy.

UUID v7 structure
018f6b5e-c913-7a2b-8d1f-3c4e5f6a7b8c
                  ^
                  version 7

First 48 bits: Unix timestamp (ms)
Remaining bits: Random

Pros: Sortable by creation time, no MAC address leak
Cons: Newer, not yet supported everywhere

UUID v7 is the recommended choice for new projects, especially for database primary keys. The timestamp prefix means IDs sort chronologically, which is significantly better for database index performance than random v4 UUIDs.

UUID v5 — Namespace + Name (SHA-1 Hash)

Deterministic: the same namespace + name always produces the same UUID. Useful when you need a stable identifier derived from a known value.

UUID v5 example
// Same inputs always produce the same UUID:
namespace = "6ba7b810-9dad-11d1-80b4-00c04fd430c8" (URL namespace)
name      = "https://devbolt.dev"
result    = "a6e5e5c0-..."  (always the same)

Use cases:
  • Generating IDs from URLs, emails, or DNS names
  • Deduplication — same input = same ID

Which Version Should You Use?

Use CaseVersionWhy
Database primary keysv7Sortable, good index performance
General unique IDsv4Simple, widely supported
Deterministic IDs from namesv5Same input = same UUID
Legacy systemsv1Only if required by existing code

Generating UUIDs in Code

JavaScript (Node.js / Browser)
// Built-in (v4) — Node.js 14.17+ and all modern browsers
const id = crypto.randomUUID();
// "3b241101-e2bb-4d7a-8613-e4bfa8964d71"

// Using the uuid package (v4)
import { v4 as uuidv4 } from "uuid";
const id = uuidv4();

// Using the uuid package (v7)
import { v7 as uuidv7 } from "uuid";
const id = uuidv7();
Python
import uuid

# v4 (random)
id = uuid.uuid4()
# UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')

# v5 (namespace + name)
id = uuid.uuid5(uuid.NAMESPACE_URL, "https://devbolt.dev")

# v7 (Python 3.14+)
id = uuid.uuid7()
Go
import "github.com/google/uuid"

// v4
id := uuid.New()
// "f47ac10b-58cc-4372-a567-0e02b2c3d479"

// v7
id, _ := uuid.NewV7()

// From string
parsed, err := uuid.Parse("550e8400-e29b-41d4-a716-446655440000")
PostgreSQL
-- v4 (built-in since PostgreSQL 13)
SELECT gen_random_uuid();

-- Use as primary key
CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  email TEXT NOT NULL
);
Command line
# macOS / Linux
uuidgen
# 5A6A8C6B-3E7D-4A2F-9B1C-8D5E6F7A8B9C

# Python one-liner
python3 -c "import uuid; print(uuid.uuid4())"

# Node.js one-liner
node -e "console.log(crypto.randomUUID())"

UUID vs Auto-Increment IDs

FeatureUUIDAuto-Increment
Size16 bytes4–8 bytes
Distributed generationNo coordination neededRequires central authority
PredictabilityNot guessableSequential, easy to enumerate
Index performancev7 good, v4 poorExcellent
URL safetyDoesn't leak countReveals total records

Auto-increment IDs leak information. If your user profile is at /users/42, attackers know you have at most 42 users and can enumerate all of them. UUIDs prevent this.

Common Mistakes

  • Using v4 as a database primary key without considering performance. Random UUIDs fragment B-tree indexes because inserts land at random positions. Use v7 for sequential inserts, or store UUIDs as BINARY(16) instead of CHAR(36).
  • Treating UUIDs as secrets. UUIDs are unique but not necessarily unpredictable (v1 is predictable). Never use a UUID as a password, API key, or security token. Use crypto.randomBytes() or a dedicated token generator instead.
  • Storing UUIDs as strings. A UUID string is 36 characters (with hyphens). Stored as CHAR(36), that's 36 bytes. Stored as a native UUID type or BINARY(16), it's only 16 bytes — less than half the storage and much faster to index.
  • Case-sensitive comparison. UUIDs are case-insensitive. 550E8400... and 550e8400... are the same UUID. Always normalize to lowercase before comparing or storing.

Running PostgreSQL with UUID primary keys?

DigitalOcean Managed Databases handle backups, failover, and scaling for PostgreSQL, MySQL, and Redis. Built-in gen_random_uuid() support with no server management.

Try It Yourself

Use our UUID Generator to generate v1, v4, and v7 UUIDs instantly in your browser. Need to verify a hash of your UUID? Try the Hash Generator. And if you're building an API that uses UUIDs, check out the JSON Formatter to validate your API responses.