Expert ReviewedUpdated 2025developer
developer
9 min readMay 30, 2025Updated Aug 22, 2025

UUID Guide: Understanding Unique Identifiers in Software Development

Learn what UUIDs are, how they work, the differences between versions, and when to use them. A complete developer guide to universally unique identifiers.

Every database record, API request, and distributed system needs unique identifiers. UUIDs (Universally Unique Identifiers) solve this elegantly—128-bit values that can be generated anywhere, anytime, with near-zero collision risk. This guide explains what UUIDs are, the differences between versions, and when to use them.

Key Takeaways

  • 1
    UUID is a 128-bit identifier: 32 hex chars in 8-4-4-4-12 format with ~340 undecillion possible values
  • 2
    UUID v4 (random) is most common; UUID v7 (time-sortable) is best for database primary keys
  • 3
    Collision probability is negligible: 2.71 quintillion UUIDs needed for 50% collision chance
  • 4
    Store as BINARY(16) in MySQL, native UUID in PostgreSQL for efficiency
  • 5
    UUIDs prevent enumeration but aren't security tokens—always validate access permissions

1What Is a UUID?

A UUID is a 128-bit identifier represented as 32 hexadecimal characters, typically displayed in 5 groups separated by hyphens: 8-4-4-4-12. The format looks like this:
550e8400-e29b-41d4-a716-446655440000
^^^^^^^^ ^^^^ ^^^^ ^^^^ ^^^^^^^^^^^^
   |       |    |    |        |
 time-low  |  version|    node (MAC or random)
      time-mid    variant
UUID specifications
PropertyValue
Size128 bits (16 bytes)
Hex characters32
Total characters (with hyphens)36
Possible values2^128 ≈ 340 undecillion
Collision probabilityNegligible (see below)
GUID vs UUID: They are the same thing. GUID (Globally Unique Identifier) is Microsoft's term. UUID (Universally Unique Identifier) is the standard term from RFC 4122. Both refer to the same 128-bit format.

2UUID Versions Explained

Not all UUIDs are created equal. The version number (the 13th character) tells you how it was generated.
UUID version comparison
VersionBased OnBest For
v1Timestamp + MAC addressLegacy systems, time ordering
v2DCE Security (POSIX UIDs)Rarely used
v3MD5 hash of namespace + nameDeterministic IDs from names
v4Random numbersGeneral purpose (most common)
v5SHA-1 hash of namespace + nameDeterministic IDs (preferred over v3)
v6Reordered timestamp + randomTime-ordered, sortable
v7Unix timestamp + randomModern sortable (recommended)
v8Custom/experimentalVendor-specific implementations
For most applications, use UUID v4 (random) or UUID v7 (time-sortable). v4 is universally supported. v7 is newer but offers database indexing benefits.

3UUID v4: The Random Standard

UUID v4 uses cryptographically random numbers for 122 of its 128 bits (6 bits are fixed for version and variant). It's the most widely used version.
// Generate UUID v4 in JavaScript (native)
const uuid = crypto.randomUUID();
console.log(uuid); // e.g., "f47ac10b-58cc-4372-a567-0e02b2c3d479"

// Using uuid package (Node.js)
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4();

// Python
import uuid
my_uuid = uuid.uuid4()

// Java
UUID uuid = UUID.randomUUID();
Collision probability: With 122 random bits, you'd need to generate 2.71 quintillion UUIDs before having a 50% chance of one duplicate. Generating 1 billion UUIDs/second would take 85 years to reach 50% collision probability.

Generate UUIDs Instantly

Create UUID v4 identifiers with one click. Copy, generate in bulk, or customize format.

Open UUID Generator

4UUID v7: The Modern Choice

UUID v7 (RFC 9562, 2024) embeds a Unix timestamp in the first 48 bits, making UUIDs naturally sortable by creation time. This offers significant database performance benefits.
UUID v7 Structure:
0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                     unix_ts_ms (32 bits)                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   unix_ts_ms (16 bits)    |  ver  |  rand_a (12 bits)         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var|              rand_b (62 bits)                             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         rand_b                                |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
UUID v7 benefits
AdvantageExplanation
Time-sortableUUIDs created later sort after earlier ones
Index-friendlySequential inserts improve B-tree performance
Timestamp extractionCan extract creation time from UUID
Still unique74 random bits prevent collisions
Drop-in replacementSame format, works with existing UUID columns
// Generate UUID v7 (using uuid package v9+)
import { v7 as uuidv7 } from 'uuid';
const id = uuidv7();
// Result: 018f6d3c-e1a2-7xxx-xxxx-xxxxxxxxxxxx
//         ^^^^^^^^^^^^
//         Timestamp portion (sortable)

5UUIDs in Databases

UUIDs are popular as primary keys, especially in distributed systems. But they come with trade-offs.
UUID vs auto-increment comparison
AspectUUIDAuto-Increment INT
Size16 bytes4-8 bytes
Uniqueness scopeGlobal (cross-database)Table only
PredictabilityUnpredictable (good for security)Sequential (predictable)
GenerationClient or serverDatabase only
Index performanceRandom inserts (slower with v4)Sequential (fast)
Merge conflictsNonePossible
URL exposureSafe (unguessable)Risky (enumerable)
-- PostgreSQL native UUID type
CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email VARCHAR(255) NOT NULL
);

-- MySQL with BINARY(16) storage (efficient)
CREATE TABLE users (
    id BINARY(16) PRIMARY KEY,
    email VARCHAR(255) NOT NULL
);

-- Insert with UUID_TO_BIN for MySQL 8+
INSERT INTO users (id, email) 
VALUES (UUID_TO_BIN(UUID()), 'user@example.com');
For best database performance: Use UUID v7 (time-sortable) and store as BINARY(16) not VARCHAR(36). This reduces storage by 56% and improves index locality.

6UUID Security Considerations

UUIDs provide obscurity, not security. Understand their limitations.
  • UUID v1 leaks MAC address and timestamp—avoid for sensitive data
  • UUID v4 is unpredictable but not a security token—always validate access
  • UUIDs prevent enumeration attacks (can't guess /users/2 from /users/1)
  • Never use UUID as the only access control—check permissions server-side
  • UUID v7 reveals creation time—may be sensitive in some contexts
UUIDs are not secrets! Anyone with the UUID can use it. For sensitive resources, combine UUIDs with proper authentication and authorization checks.
Example: Secure API Pattern

Scenario

Exposing user documents via UUID in URL

Solution

GET /documents/:uuid requires authentication. Server checks if authenticated user owns or has access to that document. UUID prevents guessing, auth prevents unauthorized access.

7When to Use UUIDs (And When Not To)

UUIDs shine in certain scenarios but add overhead in others. Choose wisely.
UUID use case recommendations
Use CaseRecommendation
Distributed systems✅ UUID (no coordination needed)
Public API resource IDs✅ UUID (prevents enumeration)
Database sharding/replication✅ UUID (no conflicts)
High-volume logging✅ UUID v7 (sortable + unique)
Internal sequential data⚠️ Consider auto-increment (simpler, smaller)
URL shorteners❌ Use short IDs (base62, nanoid)
Human-readable codes❌ Use custom formats (ABC-123)
IoT with limited storage❌ Use smaller identifiers
// Alternative: nanoid for shorter IDs
import { nanoid } from 'nanoid';
const id = nanoid();      // "V1StGXR8_Z5jdHi6B-myT" (21 chars)
const short = nanoid(10); // "IRFa-VaY2b" (10 chars)

// For URL-safe, human-readable IDs
// nanoid is 2x faster than UUID and customizable

8UUID Best Practices

Follow these guidelines for effective UUID usage in production systems.
  • Use UUID v4 for general-purpose random IDs
  • Use UUID v7 for database primary keys (time-sortable, index-friendly)
  • Store as BINARY(16) in MySQL, native UUID type in PostgreSQL
  • Generate client-side when possible to reduce server load
  • Never rely on UUID alone for access control—always authenticate
  • Use lowercase and include hyphens for standard format
  • Validate UUID format before database operations to prevent injection
  • Consider nanoid or ULID for shorter, URL-friendly identifiers
// Validate UUID format (regex)
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-7][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;

function isValidUUID(str) {
  return UUID_REGEX.test(str);
}

// Validate with uuid package
import { validate as uuidValidate, version as uuidVersion } from 'uuid';
uuidValidate('not-a-uuid'); // false
uuidValidate('f47ac10b-58cc-4372-a567-0e02b2c3d479'); // true
uuidVersion('f47ac10b-58cc-4372-a567-0e02b2c3d479'); // 4

Frequently Asked Questions

What is the difference between UUID and GUID?
They are the same thing. UUID (Universally Unique Identifier) is the standard term defined in RFC 4122. GUID (Globally Unique Identifier) is Microsoft's term for the same concept. Both refer to 128-bit identifiers in the 8-4-4-4-12 hexadecimal format.
Can two UUIDs ever be the same?
Theoretically yes, but practically never. UUID v4 has 122 random bits, giving 5.3×10^36 possible values. The probability of collision is so low that you'd need to generate 2.71 quintillion UUIDs before having a 50% chance of a single duplicate. Most systems will never see a collision.
Which UUID version should I use?
For most applications, use UUID v4 (random) for general-purpose IDs or UUID v7 (time-sortable) for database primary keys. v4 is universally supported and unpredictable. v7 offers better database index performance because sequential inserts are faster than random ones.
Are UUIDs secure for authentication?
UUIDs provide obscurity, not security. They're unguessable (you can't enumerate them like /user/1, /user/2), but anyone with a UUID can use it. Always combine UUIDs with proper authentication (who is making the request) and authorization (do they have permission) checks.
How do I store UUIDs efficiently in a database?
Store as BINARY(16) in MySQL (not VARCHAR(36)—saves 56% space). PostgreSQL has a native UUID type that's optimized. For MySQL 8+, use UUID_TO_BIN() and BIN_TO_UUID() functions. Consider UUID v7 for better index performance due to time-based ordering.