DailyTools
All articles
Developer ToolsMarch 11, 20268 min read

UUIDs Explained: Unique Identifiers for Distributed Systems and Databases

UUIDs power modern distributed systems, from database primary keys to API resources. Learn how UUID versions work, when to use each, and the trade-offs between UUIDs and auto-increment IDs.

DT
DailyTools Editorial · About

If your user IDs are sequential integers, someone can estimate how many users you have by signing up twice and comparing IDs. That's not just awkward — for some businesses it's a real competitive intelligence leak. Sequential IDs also require a central coordinator (the database sequence), which breaks down in multi-region deployments and offline-first apps. UUIDs solve both problems.

UUIDs are 128-bit values. With UUID v4, there are 2^122 possible values. At 1 billion generated per second, you'd need 85 years to have a 50% chance of a single collision. For practical purposes, collisions don't happen. The trade-off is that they're larger than integers and, if you use the wrong version, they'll wreck your database index performance.

Reading a UUID — what all those characters mean

A UUID is a 128-bit value displayed as 32 hexadecimal characters separated by hyphens in five groups: 8-4-4-4-12. For example: 550e8400-e29b-41d4-a716-446655440000. The 13th character (the first digit of the third group) indicates the UUID version. The 17th character indicates the variant (almost always 8, 9, a, or b for RFC 4122 UUIDs).

text
UUID format: xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
                                ^         ^
                                |         |
                            Version    Variant

Version 4 example: 550e8400-e29b-41d4-a716-446655440000
                                 ^
                             Version = 4 (random)

v1, v4, v7: which one you actually want

  • UUID v1 (timestamp + MAC address): Encodes the generation time and the machine's network card MAC address. Guarantees uniqueness but leaks the creation time and the generating machine's identity. Rarely used in modern systems due to privacy concerns.
  • UUID v4 (random): Generated entirely from random or pseudo-random numbers. The most widely used version — simple to implement, no information leakage, no coordination required. The collision probability for 2^122 possible values is vanishingly small: you would need to generate 1 billion UUIDs per second for 85 years to have a 50% chance of a single collision.
  • UUID v7 (timestamp-ordered, 2022): A newer standard that embeds a Unix timestamp in the first 48 bits, making UUIDs sortable by creation time while remaining unique. This solves the database index performance problem of random v4 UUIDs. Supported by modern libraries and gaining rapid adoption.

If you're starting a new project in 2026, use UUID v7 for primary keys. It's time-ordered (B-tree indexes stay happy), it's in RFC 9562, and major libraries already support it. The old debate between UUID v4 and auto-increment is largely resolved by v7 — you get coordination-free generation and good index performance.

Why random IDs matter more than you think

The performance argument against UUIDs is real. The security and architecture arguments for them are also real. Here's the breakdown:

  • Information leakage: Sequential IDs reveal your record count, growth rate, and creation order. UUID v4 reveals nothing. This matters for user-facing IDs in URLs and APIs.
  • ID generation without coordination: Auto-increment requires a centralized sequence (the database). UUIDs can be generated by any client, server, or service independently — critical for offline-first apps and microservices.
  • Database index performance: Random UUID v4 values cause B-tree index fragmentation because inserts scatter across the index rather than appending at the end. This increases write amplification and slows queries on large tables. UUID v7 solves this with time-ordered prefixes.
  • Storage size: An integer ID uses 4-8 bytes. A UUID uses 16 bytes (as binary) or 36 bytes (as a string). On tables with millions of rows and multiple indexes, this difference compounds.
  • Human readability: Order #12847 is easy to communicate over the phone. UUID 550e8400-e29b-41d4-a716-446655440000 is not.

Generating UUIDs in Code

javascript
// Browser — crypto.randomUUID() (CSPRNG, UUID v4)
const id = crypto.randomUUID();
// → "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed"

// Node.js — built-in since v14.17
const { randomUUID } = require('crypto');
const id = randomUUID();

// Python
import uuid
id = uuid.uuid4()  # Random UUID v4

// PostgreSQL — built-in function
-- UUID v4 (requires pgcrypto or gen_random_uuid in PG 13+)
SELECT gen_random_uuid();

// Store UUIDs as binary (16 bytes) not strings (36 bytes)
-- PostgreSQL: use the native UUID type
-- MySQL: use BINARY(16) with UUID_TO_BIN() / BIN_TO_UUID()

What I'd tell a junior dev about UUID storage

  • Store UUIDs as binary (16 bytes), not as VARCHAR(36) strings — saves 55% storage and dramatically improves index performance
  • Prefer UUID v7 for primary keys — time-ordered prefixes maintain B-tree insert performance comparable to auto-increment
  • If using UUID v4, consider a separate auto-increment column for the clustered index and use the UUID as a secondary unique index for external lookups
  • PostgreSQL's native UUID type stores 16 bytes and supports indexing efficiently — always use it over text
  • In MySQL, use UUID_TO_BIN(uuid, 1) with the swap flag to reorder bytes for better index locality

When UUID v4 isn't quite right

Several alternative ID formats address specific UUID shortcomings:

  • ULID (Universally Unique Lexicographically Sortable Identifier): 128-bit, time-ordered, Crockford Base32 encoded (26 characters). Monotonically sortable within the same millisecond. A popular UUID v7 alternative.
  • Snowflake IDs (Twitter): 64-bit integers encoding timestamp + machine ID + sequence number. Compact, sortable, and unique across a coordinated cluster. Used by Twitter, Discord, and Instagram.
  • NanoID: Customizable-length random string using a URL-safe alphabet. Shorter than UUIDs (21 characters by default) with comparable collision resistance. Popular for user-facing IDs.
  • CUID2: Collision-resistant, horizontally scalable IDs designed specifically for web applications. Monotonically sorted, URL-safe, and shorter than UUIDs.

Try the free tool referenced in this article

UUID Generator