Guide · Developer security
UUID Version Comparison: v1 vs v4 vs v5
A comprehensive comparison of UUID versions 1, 4, and 5, including their differences, use cases, security implications, and implementation considerations.
UUID Version Overview
UUID (Universally Unique Identifier) comes in several versions, each with different generation methods and use cases. Understanding these differences is crucial for choosing the right UUID type for your application.
UUID v1
MethodTimestamp + MAC addressEntropy74 bits + timestampUniquenessGlobally uniquePrivacyReveals MAC addressUUID v4
MethodRandom/pseudo-randomEntropy122 bitsUniquenessStatistically uniquePrivacyNo identifying informationUUID v5
MethodSHA-1 hash of namespace + nameEntropyDeterministic (no randomness)UniquenessDeterministic uniquenessPrivacyMay reveal input patternsUUID v1: Timestamp-Based
How UUID v1 Works
UUID v1 generates identifiers based on the current timestamp and the MAC address of the generating machine:
// UUID v1 structure
xxxxxxxx-xxxx-1xxx-xxxx-xxxxxxxxxxxx
// Breakdown:
// 32-bit: Low field of timestamp
// 16-bit: Middle field of timestamp
// 16-bit: High field of timestamp (version 1)
// 16-bit: Clock sequence and reserved bits
// 48-bit: Node (MAC address)UUID v1 Example
// Example UUID v1
58a3b6e0-2c5a-11ee-b679-0242ac110002
// Decoded information:
// Timestamp: 2023-08-10 14:30:45.123456 UTC
// Clock sequence: 0x2679
// MAC address: 02:42:ac:11:00:02UUID v1 Pros & Cons
- Guaranteed uniqueness across machines
- Sortable by creation time
- Can extract timestamp information
- Very fast generation
- No collision risk (with proper clock sync)
- Reveals MAC address (privacy concern)
- Reveals creation timestamp
- Requires system clock synchronization
- Sequential nature aids database attacks
- Not suitable for security-sensitive applications
When to Use UUID v1
- Legacy systems: When compatibility with older systems is required
- Distributed logging: When you need sortable IDs with timestamp info
- Internal systems: When MAC address exposure isn't a concern
- High throughput: When generation speed is critical
UUID v4: Random-Based
How UUID v4 Works
UUID v4 generates identifiers using random or pseudo-random numbers:
// UUID v4 structure
xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
// Breakdown:
// 122 bits: Random data
// 4 bits: Version (always 0100 = 4)
// 2 bits: Variant (always 10)
// Total: 128 bits (122 random + 6 fixed)UUID v4 Example
// Example UUID v4
f47ac10b-58cc-4372-a567-0e02b2c3d479
// All 'x' positions are random hex digits
// The '4' indicates version 4
// The 'y' is one of 8, 9, a, or b (variant bits)UUID v4 Collision Probability
Collision probability with 122 bits of randomness:
1 billion UUIDs1 in 5.3 × 10²⁷ chance1 trillion UUIDs1 in 5.3 × 10²¹ chancePractical riskEffectively zero for real applicationsUUID v4 Pros & Cons
- No identifying information revealed
- Excellent privacy properties
- Simple implementation
- No coordination required
- Cryptographically secure randomness
- Statistically unique
- Not sortable by creation time
- Theoretical collision possibility
- Requires good random number source
- No timestamp information available
- Database index performance impact
When to Use UUID v4
- Web applications: User accounts, session IDs, API keys
- Public APIs: Resource identifiers, transaction IDs
- Distributed systems: Service discovery, message IDs
- Security applications: When privacy is paramount
- General purpose: Default choice for most applications
UUID v5: Name-Based (SHA-1)
How UUID v5 Works
UUID v5 generates identifiers by computing SHA-1 hash of a namespace UUID and a name:
// UUID v5 generation process
1. Choose a namespace UUID
2. Concatenate namespace UUID + name
3. Compute SHA-1 hash
4. Format as UUID with version 5 bits
// Structure
xxxxxxxx-xxxx-5xxx-yxxx-xxxxxxxxxxxx
// The hash is deterministic - same input always produces same UUIDStandard Namespaces
6ba7b810-9dad-11d1-80b4-00c04fd430c8DNS namespace6ba7b811-9dad-11d1-80b4-00c04fd430c8URL namespace6ba7b812-9dad-11d1-80b4-00c04fd430c8OID namespace6ba7b814-9dad-11d1-80b4-00c04fd430c8X.500 namespaceUUID v5 Examples
// Generate UUID v5 for domain name
const uuidv5 = require('uuid/v5');
// DNS namespace
const DNS_NAMESPACE = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
// Always generates the same UUID for the same input
const uuid1 = uuidv5('example.com', DNS_NAMESPACE);
const uuid2 = uuidv5('example.com', DNS_NAMESPACE);
// uuid1 === uuid2 (always true)
console.log(uuid1); // 9073926b-929f-31c2-abc9-fad77ae3e8eb
// URL namespace
const URL_NAMESPACE = '6ba7b811-9dad-11d1-80b4-00c04fd430c8';
const urlUuid = uuidv5('https://example.com/page', URL_NAMESPACE);
console.log(urlUuid); // c6235813-3ba4-3801-ae84-e0a6ebb7d138UUID v5 Pros & Cons
- Deterministic - same input = same output
- No random number generation required
- Useful for creating consistent IDs
- Good for mapping external identifiers
- Reproducible across systems
- No storage of previous UUIDs needed
- Uses SHA-1 (cryptographically weak)
- Input can potentially be guessed
- May reveal patterns in input data
- Not suitable for security-critical applications
- Requires namespace planning
- No timestamp information
When to Use UUID v5
- Content addressing: Creating consistent IDs for content
- External ID mapping: Converting external identifiers to UUIDs
- Reproducible builds: When deterministic IDs are needed
- Distributed caching: Consistent cache keys across systems
- Testing: Deterministic UUIDs for test cases
Performance Comparison
Generation Speed
Approximate generation times (per UUID):
UUID v1~0.1 μs (fastest - uses timestamp + MAC)UUID v4~0.5 μs (depends on random number generation)UUID v5~2.0 μs (SHA-1 computation overhead)Database Index Performance
UUID v1Good (sequential, time-ordered)UUID v4Poor (random, causes index fragmentation)UUID v5Variable (depends on input distribution)Storage Considerations
All UUID versions use the same 128-bit storage format, but their impact differs:
- PostgreSQL: Consider using UUID v1 for primary keys to reduce B-tree fragmentation
- MySQL: UUID v4 can cause significant page splits with InnoDB
- NoSQL: UUID v4 randomness is generally less problematic
Security Implications
Information Leakage
UUID v1❌ Reveals MAC address and timestampUUID v4✅ No information leakageUUID v5⚠️ May reveal patterns in input dataPredictability
UUID v1❌ Predictable (sequential timestamp)UUID v4✅ Cryptographically unpredictableUUID v5❌ Deterministic (same input = same output)Collision Resistance
UUID v1✅ Excellent (guaranteed with clock sync)UUID v4✅ Excellent (122 bits entropy)UUID v5⚠️ Good (depends on SHA-1 strength)Implementation Examples
Node.js Implementation
const { v1: uuidv1, v4: uuidv4, v5: uuidv5 } = require('uuid');
// UUID v1 - timestamp based
const uuid1 = uuidv1();
console.log(uuid1); // e.g., 58a3b6e0-2c5a-11ee-b679-0242ac110002
// UUID v4 - random
const uuid4 = uuidv4();
console.log(uuid4); // e.g., f47ac10b-58cc-4372-a567-0e02b2c3d479
// UUID v5 - name based
const DNS_NAMESPACE = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
const uuid5 = uuidv5('example.com', DNS_NAMESPACE);
console.log(uuid5); // e.g., 9073926b-929f-31c2-abc9-fad77ae3e8eb
// Custom namespace UUID v5
const CUSTOM_NAMESPACE = uuidv4(); // Generate once, reuse
const customUuid = uuidv5('my-unique-name', CUSTOM_NAMESPACE);Python Implementation
import uuid
# UUID v1 - timestamp based
uuid1 = uuid.uuid1()
print(uuid1) # e.g., 58a3b6e0-2c5a-11ee-b679-0242ac110002
# UUID v4 - random
uuid4 = uuid.uuid4()
print(uuid4) # e.g., f47ac10b-58cc-4372-a567-0e02b2c3d479
# UUID v5 - name based
uuid5_dns = uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
print(uuid5_dns) # e.g., 9073926b-929f-31c2-abc9-fad77ae3e8eb
uuid5_url = uuid.uuid5(uuid.NAMESPACE_URL, 'https://example.com')
print(uuid5_url) # e.g., c6235813-3ba4-3801-ae84-e0a6ebb7d138Java Implementation
import java.util.UUID;
import java.security.MessageDigest;
// UUID v4 - random (standard library)
UUID uuid4 = UUID.randomUUID();
System.out.println(uuid4); // e.g., f47ac10b-58cc-4372-a567-0e02b2c3d479
// UUID v5 - name based (custom implementation)
public static UUID uuid5(UUID namespace, String name) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(namespace.toString().getBytes());
md.update(name.getBytes());
byte[] hash = md.digest();
// Set version to 5
hash[6] &= 0x0f;
hash[6] |= 0x50;
// Set variant
hash[8] &= 0x3f;
hash[8] |= 0x80;
return UUID.nameUUIDFromBytes(hash);
} catch (Exception e) {
throw new RuntimeException(e);
}
}Best Practices by Use Case
Web Applications
- User IDs, session tokens, API keys
- Resource identifiers in REST APIs
- Transaction and order IDs
- Any public-facing identifier
Database Primary Keys
- UUID v1 for better index performance
- UUID v4 when privacy is more important
- Consider ULID as alternative (sortable + random)
- Avoid UUID primary keys for high-write tables
Content-Addressable Storage
- File system content addressing
- Git-like version control systems
- Distributed caching with consistent keys
- Mapping external identifiers to internal UUIDs
Microservices & Logging
- UUID v1 for request/trace IDs (sortable by time)
- UUID v4 for service instances and resources
- UUID v5 for deterministic service discovery
- Consider correlation ID patterns
Decision Framework
Quick Decision Tree
Do you need deterministic UUIDs (same input = same output)?
- ✅ Yes → Use UUID v5
- ❌ No → Continue...
Do you need time-ordered/sortable UUIDs?
- ✅ Yes → Use UUID v1 (accept privacy trade-off)
- ❌ No → Continue...
Is this for a public-facing application?
- ✅ Yes → Use UUID v4
- ❌ No → UUID v1 or v4 based on performance needs