UUID Generator
Generate UUIDs (Universally Unique Identifiers) in multiple versions. Perfect for unique identifiers, testing, and resource naming.
What is a UUID?
A UUID (Universally Unique Identifier) is a 128-bit identifier that is designed to be unique across time and space without requiring a central coordinating authority. UUIDs are also known as GUIDs (Globally Unique Identifiers) in Microsoft's terminology.
UUIDs are represented as 32 hexadecimal digits, displayed in five groups separated by hyphens:
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Example UUID:
550e8400-e29b-41d4-a716-446655440000
Why UUIDs Matter
- Distributed systems: Generate unique IDs without coordination
- Database primary keys: Avoid collisions across multiple databases
- API resource identifiers: Unique resource IDs in REST APIs
- Session management: Unique session identifiers
- File naming: Unique filenames without conflicts
- Cloud resources: Unique identifiers for cloud resources
UUID Format
Structure
A UUID consists of 128 bits (16 bytes) represented as 32 hexadecimal digits:
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
Where:
xxxxxxxx-xxxx: Time low (v1) or random (v4)Mxxx: Version number (1-7) in the most significant 4 bitsNxxx: Variant bits (identifies UUID layout)xxxxxxxxxxxx: Node ID (v1) or random (v4)
Version Numbers
The version is encoded in the 13th character (4 bits):
| Version | Character | Description |
|---|---|---|
| v1 | 1 | Time-based UUID |
| v2 | 2 | DCE Security UUID (rarely used) |
| v3 | 3 | Name-based UUID (MD5) |
| v4 | 4 | Random UUID (most common) |
| v5 | 5 | Name-based UUID (SHA-1) |
| v6 | 6 | Time-ordered UUID (RFC 9562) |
| v7 | 7 | Time-ordered random UUID (RFC 9562) |
Variant Bits
The variant is encoded in the 17th character (2-3 bits):
- Variant 10 (
8,9,a,b): Standard UUID variant (most common) - Variant 110 (
c,d): Microsoft GUID variant - Variant 1110 (
e): Reserved for future use - Variant 1111 (
f): Reserved for future use
UUID Versions Explained
UUID v1 (Time-based)
Characteristics:
- Based on MAC address and timestamp
- Contains timestamp information
- Can be traced back to creation time
- Not recommended for privacy-sensitive applications
Format:
time_low-time_mid-time_high_and_version-clock_seq_high_and_reserved-clock_seq_low-node
Use cases:
- Legacy systems
- When temporal ordering is needed
- Systems that need to extract creation time
Example:
6ba7b810-9dad-11d1-80b4-00c04fd430c8
UUID v3 (Name-based, MD5)
Characteristics:
- Deterministic: Same namespace + name = same UUID
- Uses MD5 hashing (deprecated)
- Not cryptographically secure
- Prefer v5 over v3
Format:
hash(namespace_uuid + name)
Namespaces:
- DNS:
6ba7b810-9dad-11d1-80b4-00c04fd430c8 - URL:
6ba7b811-9dad-11d1-80b4-00c04fd430c8 - OID:
6ba7b812-9dad-11d1-80b4-00c04fd430c8 - X.500:
6ba7b814-9dad-11d1-80b4-00c04fd430c8
Use cases:
- Legacy systems requiring MD5
- When deterministic UUIDs are needed (not recommended)
Example:
// Same input always produces same UUID
uuid.v3('dns', 'example.com') // Always: 9073926b-929f-31c2-aa52-f5a5b9e8c123UUID v4 (Random)
Characteristics:
- Most commonly used version
- Cryptographically random
- No embedded information (timestamp, MAC address)
- Best for privacy
- Collision probability is extremely low
Format:
random-random-4xxx-random-random
Use cases:
- Primary keys in databases
- API resource identifiers
- Session tokens
- File naming
- Most general-purpose unique identifiers
Example:
550e8400-e29b-41d4-a716-446655440000
Collision probability:
- For 1 billion UUIDs: ~0.00000006% chance of collision
- Practically zero for most applications
UUID v5 (Name-based, SHA-1)
Characteristics:
- Deterministic: Same namespace + name = same UUID
- Uses SHA-1 hashing (more secure than MD5)
- Preferred over v3
- Not cryptographically secure (SHA-1 is deprecated)
Format:
hash(namespace_uuid + name)
Use cases:
- Generating UUIDs from URLs, domain names, or other names
- When deterministic UUIDs are needed
- Content addressing
- Distributed systems needing consistent IDs
Example:
// Same input always produces same UUID
uuid.v5('dns', 'example.com') // Always: 9073926b-929f-51c2-aa52-f5a5b9e8c123UUID v6 (Time-ordered, RFC 9562)
Characteristics:
- Similar to v1 but with reordered fields
- Better for database indexing (time-ordered)
- Contains timestamp information
- Newer standard (RFC 9562, 2024)
Format:
time_high-time_mid-time_low_and_version-clock_seq_high_and_reserved-clock_seq_low-node
Use cases:
- Database primary keys (better indexing than v4)
- When temporal ordering is important
- Log entries
- Event streams
Example:
1e74ba22-7b62-61d1-80b4-00c04fd430c8
UUID v7 (Time-ordered Random, RFC 9562)
Characteristics:
- Combines Unix timestamp (milliseconds) with randomness
- Time-ordered for better database performance
- No MAC address (privacy-friendly)
- Newer standard (RFC 9562, 2024)
- Recommended for new applications
Format:
unix_timestamp_ms-random-random-random
Use cases:
- Modern database primary keys
- API resource identifiers
- Event logging
- When you need time ordering + randomness
Example:
018b0c3a-7b62-7000-8000-123456789abc
When to Use Each Version
| Version | Use When | Don't Use When |
|---|---|---|
| v1 | Legacy systems, need creation time | Privacy-sensitive, modern systems |
| v3 | Legacy systems only | New projects (use v5 instead) |
| v4 | General purpose, privacy important | Need time ordering, deterministic IDs |
| v5 | Need deterministic UUIDs from names | Need random UUIDs |
| v6 | Need time ordering + MAC address info | Privacy-sensitive, modern systems |
| v7 | Modern apps, need time ordering | Legacy systems that don't support it |
Common Use Cases
1. Database Primary Keys
PostgreSQL:
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
-- Insert with UUID
INSERT INTO users (id, email)
VALUES ('550e8400-e29b-41d4-a716-446655440000', 'user@example.com');MySQL:
CREATE TABLE users (
id CHAR(36) PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Insert with UUID
INSERT INTO users (id, email)
VALUES (UUID(), 'user@example.com');2. REST API Resource Identifiers
Example API:
// GET /api/users/550e8400-e29b-41d4-a716-446655440000
app.get('/api/users/:id', (req, res) => {
const userId = req.params.id;
// Validate UUID format
if (!isValidUuid(userId)) {
return res.status(400).json({ error: 'Invalid UUID format' });
}
// Fetch user...
});Benefits:
- Opaque identifiers (don't reveal internal structure)
- No sequential IDs (prevents enumeration attacks)
- Globally unique (no conflicts across services)
3. Distributed Systems
Microservices:
// Generate correlation ID for request tracing
const correlationId = generateUuidV4();
// Pass through all service calls
fetch('https://api.service.com/data', {
headers: {
'X-Correlation-ID': correlationId
}
});Event Sourcing:
const event = {
id: generateUuidV4(),
type: 'UserCreated',
aggregateId: generateUuidV4(),
timestamp: new Date(),
data: { /* ... */ }
};4. File Naming
Unique file uploads:
const fileExtension = originalFilename.split('.').pop();
const uniqueFilename = `${generateUuidV4()}.${fileExtension}`;
// Result: 550e8400-e29b-41d4-a716-446655440000.jpgBenefits:
- No filename conflicts
- Opaque (doesn't reveal file content)
- URL-safe
5. Session Management
Session tokens:
const sessionId = generateUuidV4();
sessions.set(sessionId, {
userId: user.id,
createdAt: Date.now(),
expiresAt: Date.now() + (24 * 60 * 60 * 1000) // 24 hours
});6. Cloud Resource Naming
AWS S3 buckets:
const bucketName = `my-app-${generateUuidV4()}`;
// Result: my-app-550e8400-e29b-41d4-a716-446655440000Kubernetes resources:
apiVersion: v1
kind: Secret
metadata:
name: secret-550e8400-e29b-41d4-a716-446655440000
type: Opaque
data:
# ...7. Content Addressing
Using UUID v5 for deterministic IDs:
// Generate consistent UUID from URL
const contentId = generateUuidV5('url', 'https://example.com/article/123');
// Same URL always produces same UUIDUUID Generation in Different Languages
JavaScript/TypeScript
Using crypto API:
function generateUuidV4() {
const array = new Uint8Array(16);
crypto.getRandomValues(array);
// Set version (4) and variant bits
array[6] = (array[6] & 0x0f) | 0x40;
array[8] = (array[8] & 0x3f) | 0x80;
// Convert to hex string
const hex = Array.from(array)
.map(b => b.toString(16).padStart(2, '0'))
.join('');
return [
hex.slice(0, 8),
hex.slice(8, 12),
hex.slice(12, 16),
hex.slice(16, 20),
hex.slice(20, 32),
].join('-');
}Using libraries:
// uuid package
import { v4 as uuidv4, v5 as uuidv5 } from 'uuid';
const id = uuidv4();
const nameBasedId = uuidv5('example.com', uuidv5.DNS);Python
Using uuid module:
import uuid
# v4 (random)
id = uuid.uuid4()
print(str(id)) # 550e8400-e29b-41d4-a716-446655440000
# v5 (name-based)
id = uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
print(str(id)) # 9073926b-929f-51c2-aa52-f5a5b9e8c123
# v1 (time-based)
id = uuid.uuid1()Go
Using google/uuid:
import "github.com/google/uuid"
// v4 (random)
id := uuid.New()
fmt.Println(id.String()) // 550e8400-e29b-41d4-a716-446655440000
// v5 (name-based)
namespace := uuid.NameSpaceDNS
id := uuid.NewSHA1(namespace, []byte("example.com"))
fmt.Println(id.String())Java
Using java.util.UUID:
import java.util.UUID;
// v4 (random)
UUID id = UUID.randomUUID();
System.out.println(id.toString()); // 550e8400-e29b-41d4-a716-446655440000
// v3 (name-based, MD5)
UUID namespace = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
UUID id = UUID.nameUUIDFromBytes("example.com".getBytes());UUID Validation
Format Validation
Regex pattern:
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
function isValidUuid(uuid) {
return uuidRegex.test(uuid);
}Validation checks:
- Format: 8-4-4-4-12 hexadecimal digits
- Version: Valid version number (1-7)
- Variant: Valid variant bits
Version Detection
function getUuidVersion(uuid) {
const hex = uuid.replace(/-/g, '');
const version = parseInt(hex[12], 16);
return version;
}
getUuidVersion('550e8400-e29b-41d4-a716-446655440000'); // 4Best Practices
1. Choose the Right Version
- v4: Default choice for most applications
- v7: Modern choice when time ordering is beneficial
- v5: When you need deterministic UUIDs from names
- v1/v6: Only when you need time-based ordering
2. Database Indexing
UUID v4 (random):
- Poor for B-tree indexes (random insertion)
- Consider UUID v7 for better index performance
UUID v7 (time-ordered):
- Better for database indexes
- Sequential insertion improves performance
PostgreSQL:
-- v4: Random, poor index performance
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
);
-- v7: Time-ordered, better index performance
-- (Requires custom function or application-level generation)3. Storage Considerations
Binary storage:
- Store as 16 bytes (binary) instead of 36 characters (string)
- Saves ~56% storage space
- Faster comparisons
PostgreSQL:
-- String (36 bytes)
id UUID
-- Binary (16 bytes) - if supported
id BYTEA4. URL Safety
UUIDs are URL-safe:
https://api.example.com/users/550e8400-e29b-41d4-a716-446655440000
No encoding needed (unlike some other ID formats).
5. Privacy Considerations
Avoid v1/v6 for sensitive data:
- Contains MAC address (v1) or timestamp
- Can reveal information about creation
Use v4/v7 for privacy:
- No embedded information
- Cryptographically random
6. Performance
Generation speed:
- v4: Fastest (pure random)
- v7: Fast (timestamp + random)
- v5: Slower (requires hashing)
- v1/v6: Moderate (timestamp calculation)
Database performance:
- v7 > v6 > v1 > v4 (for sequential inserts)
- v4: Random inserts cause index fragmentation
Common Mistakes to Avoid
1. Using Sequential IDs Instead of UUIDs
Problem:
// Sequential IDs reveal information
GET /api/users/1
GET /api/users/2
GET /api/users/3Solution:
// UUIDs are opaque
GET /api/users/550e8400-e29b-41d4-a716-4466554400002. Not Validating UUID Format
Problem:
// No validation
const userId = req.params.id;
db.query('SELECT * FROM users WHERE id = ?', [userId]);Solution:
// Validate format
if (!isValidUuid(userId)) {
return res.status(400).json({ error: 'Invalid UUID' });
}3. Using v1 for Privacy-Sensitive Data
Problem:
// v1 contains MAC address
const userId = generateUuidV1(); // Can be tracedSolution:
// Use v4 for privacy
const userId = generateUuidV4(); // No embedded info4. Storing as String Instead of Binary
Problem:
-- 36 bytes per UUID
id VARCHAR(36)Solution:
-- 16 bytes per UUID (if supported)
id UUID -- or BINARY(16)5. Not Considering Database Performance
Problem:
-- Random UUIDs cause index fragmentation
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid() -- v4
);Solution:
-- Use time-ordered UUIDs (v7) for better performance
-- Or use application-level generation with v7Frequently Asked Questions
What's the difference between UUID and GUID?
UUID and GUID are essentially the same thing:
- UUID: Standard term (RFC 4122)
- GUID: Microsoft's term (Globally Unique Identifier)
Both refer to the same 128-bit identifier format.
Can UUIDs collide?
Theoretically: Yes, but the probability is extremely low.
Practically: For 1 billion UUIDs, collision probability is ~0.00000006%. For most applications, collisions are not a concern.
Should I use UUIDs as primary keys?
Pros:
- Globally unique
- Opaque (don't reveal information)
- No coordination needed
Cons:
- Larger than integers (16 bytes vs 4-8 bytes)
- Slower indexing (for random UUIDs)
- Less human-readable
Recommendation: Use UUIDs when you need global uniqueness or are building distributed systems. Consider UUID v7 for better database performance.
What's the difference between v4 and v7?
- v4: Pure random, no time information
- v7: Time-ordered random, contains Unix timestamp
v7 advantages:
- Better database index performance
- Can extract creation time
- Still privacy-friendly (no MAC address)
Can I extract the creation time from a UUID?
v1/v6: Yes, timestamp is embedded v7: Yes, Unix timestamp (milliseconds) is embedded v4: No, purely random v3/v5: No, based on namespace + name
Are UUIDs secure?
v4/v7: Cryptographically random, suitable for security-sensitive applications v3/v5: Not cryptographically secure (MD5/SHA-1 are deprecated) v1/v6: Contain MAC address, not recommended for privacy
How do I convert UUID to binary?
JavaScript:
function uuidToBinary(uuid) {
const hex = uuid.replace(/-/g, '');
const bytes = new Uint8Array(16);
for (let i = 0; i < 16; i++) {
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
}
return bytes;
}PostgreSQL:
-- Convert to binary
SELECT uuid_send('550e8400-e29b-41d4-a716-446655440000'::uuid);