← Back to Blog
UUIDDatabasesBackend

UUID Guide: What They Are and When to Use Them

What is a UUID?

A UUID (Universally Unique Identifier) is a 128-bit identifier that's designed to be unique across space and time without requiring a central authority. You've probably seen them — they look like this:

550e8400-e29b-41d4-a716-446655440000

That's 32 hexadecimal characters arranged in five groups separated by hyphens, following the pattern 8-4-4-4-12. UUIDs are defined by RFC 4122 and are used everywhere: database primary keys, API identifiers, session tokens, distributed systems, message queues, and more.

The beauty of UUIDs is that you can generate them independently on any machine, at any time, and be virtually certain they won't collide with any other UUID ever generated.

UUID Versions Explained

Not all UUIDs are created equal. There are several versions, each with different generation strategies:

UUID v1 — Timestamp + MAC Address

Version 1 UUIDs combine a timestamp with the MAC address of the generating machine. They're guaranteed unique (assuming the clock doesn't go backward), but they leak information — anyone can extract the time of creation and the hardware address. For this reason, v1 is rarely used in modern applications.

UUID v4 — Random

Version 4 is by far the most popular. It's generated from random (or pseudo-random) numbers. With 122 bits of randomness, the probability of a collision is astronomically low — you'd need to generate about 2.71 × 10^18 UUIDs to have a 50% chance of a single collision.

Most developers reach for v4 by default, and for good reason: it's simple, unpredictable, and has no external dependencies.

UUID v5 — Name-Based (SHA-1)

Version 5 generates a deterministic UUID from a namespace and a name using SHA-1 hashing. Given the same inputs, you always get the same UUID. This is useful when you need reproducible identifiers — for example, generating consistent IDs from URLs or email addresses.

UUID v7 — Timestamp-Ordered Random

UUID v7 is the newest addition (from the updated RFC 9562) and is quickly gaining popularity. It embeds a Unix timestamp in the most significant bits, making v7 UUIDs naturally sortable by creation time while still having enough random bits for uniqueness.

This solves a major problem with v4 in databases: random UUIDs cause poor index locality in B-tree indexes, leading to fragmented writes. UUID v7 values are monotonically increasing, so they insert efficiently — similar to auto-increment IDs but without coordination.

When to Use UUIDs

UUIDs shine in specific scenarios:

Distributed systems. When multiple services or nodes need to create identifiers independently without talking to each other, UUIDs eliminate the need for a centralized ID generator.

Public-facing identifiers. Exposing sequential integer IDs in URLs (like /users/42) reveals information about your data — how many users you have, the order they signed up, etc. UUIDs are opaque and don't leak this context.

Merge-friendly data. If you need to merge data from multiple sources (like syncing offline databases), UUIDs prevent ID conflicts that would occur with auto-incrementing integers.

Event tracking and logging. Assigning UUIDs to requests, transactions, or events makes it easy to trace them across distributed services.

When NOT to Use UUIDs

UUIDs aren't always the right choice:

High-performance primary keys. In databases like MySQL with InnoDB, random UUIDs (v4) as primary keys cause index page splits and fragmentation. If you must use UUIDs as primary keys, prefer UUID v7 or store them as BINARY(16) instead of CHAR(36) to save space.

Human-readable identifiers. Nobody wants to read out 550e8400-e29b-41d4-a716-446655440000 over the phone. For user-facing identifiers (order numbers, confirmation codes), use shorter formats like NanoID or custom alphanumeric codes.

Small datasets. If you have a single database with a users table that'll never exceed a few million rows, a simple auto-incrementing integer is simpler, smaller (4-8 bytes vs 16 bytes), and faster.

UUID Best Practices

Storage

Store UUIDs as BINARY(16) or a native UUID type when your database supports it (PostgreSQL has a built-in uuid type). Storing as CHAR(36) works but wastes space — 36 bytes for the string representation versus 16 bytes in binary.

Generation

Use your language's built-in UUID library rather than rolling your own:

// Node.js
import { randomUUID } from 'crypto';
const id = randomUUID();
# Python
import uuid
id = uuid.uuid4()
// Go (with google/uuid)
id := uuid.New()

Indexing

If using UUIDs as database primary keys, consider:

  • PostgreSQL: Native uuid type works great; consider uuid v7 for ordered inserts
  • MySQL: Use BINARY(16) with UUID_TO_BIN() and BIN_TO_UUID() functions, or switch to v7
  • Add a secondary integer index if you need fast range queries

Validation

Always validate UUID format when accepting them from external input. A simple regex works:

^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$

Generating UUIDs

Need a quick UUID for development, testing, or configuration? You can generate UUIDs instantly with our free tool — supporting v4 and v7, with bulk generation and one-click copy.

For production code, always use a cryptographically secure random number generator (CSRNG) for v4 UUIDs. Most standard libraries handle this correctly, but be cautious with third-party packages.

The Future of UUIDs

The updated RFC 9562 (published 2024) formally introduced UUID v7, which addresses the biggest complaint about UUIDs in databases — poor index performance. With v7 gaining native support in more libraries and databases, UUIDs are becoming an even better choice for distributed identifier generation.

Whether you're building microservices, designing a database schema, or just need a unique string for a config file, understanding UUID versions and their trade-offs helps you make the right choice for your use case.

Try the tool mentioned in this article:

Open Tool →