UUIDs Explained: Versions, Use Cases, and When to Use Auto-Increment Instead
Source: Dev.to
UUIDs (Universally Unique Identifiers) appear in virtually every modern application — database primary keys, API resource IDs, session tokens, file names, correlation IDs. But there are several UUID versions, they have different tradeoffs, and auto-increment integers are often the better choice. Here is a practical breakdown. A UUID is a 128-bit identifier represented as 32 hexadecimal digits in 5 groups separated by hyphens: 550e8400-e29b-41d4-a716-446655440000
The format is 8-4-4-4-12 characters. The third group’s first digit indicates the version (above: 4). The fourth group’s first digit indicates the variant. The mathematical probability of two UUIDs colliding when generated properly is so low that it is treated as impossible in practice. UUID v1 — time-based + MAC address UUID v4 — random UUID v5 — name-based (SHA-1) UUID v7 — time-ordered random (newest) JavaScript (browser / Node.js, modern): const id = crypto.randomUUID(); // native, no library needed
Node.js (with uuid package): import { v4 as uuidv4 } from ‘uuid’; const id = uuidv4();
Python: import uuid id = str(uuid.uuid4())
Go: import “github.com/google/uuid” id := uuid.New().String()
Ruby: require ‘securerandom’ id = SecureRandom.uuid
PostgreSQL: SELECT gen_random_uuid(); — PostgreSQL 13+
UUID v7 is newer and not universally supported yet, but is available via libraries: JavaScript: import { v7 as uuidv7 } from ‘uuid’; // uuid package v9+ const id = uuidv7();
Python: import uuid id = str(uuid.uuid7()) # Python 3.13+
Java: // JUG library UUID id = Generators.timeBasedEpochGenerator().generate();
.NET 9+: Guid id = Guid.CreateVersion7();
This is the most important practical question, and the answer depends on your use case. Use auto-increment integers when: The ID is internal only — users never see it, it never appears in URLs You need the most compact storage (4 or 8 bytes vs 16 bytes for UUID) Sequential ordering of IDs is meaningful (you want to know that row 1001 was inserted after row 1000) You are on a single database server with no replication or merging concerns Use UUIDs when: IDs appear in URLs, APIs, or client-side code (UUIDs don’t reveal count or sequence) You are generating IDs on the client before writing to the database (mobile, offline-first apps) You have multiple database nodes, replicas, or data that needs to merge without ID conflicts You are building a microservices architecture where services create records independently Prefer UUID v7 over v4 for database primary keys — random v4 UUIDs cause index fragmentation because each new row inserts into a random position in the B-tree index. UUID v7’s time-ordered prefix means new rows append near the end, like auto-increment, but with global uniqueness. Storing UUIDs as VARCHAR. UUIDs should be stored as the native UUID type in PostgreSQL (16 bytes) or as BINARY(16) in MySQL. Storing as CHAR(36) or VARCHAR(36) triples the storage and slows index operations. Using UUID v4 for high-volume database tables. For tables with millions of rows, use v7 or ulid instead of v4 to avoid index fragmentation. Trusting client-generated UUIDs without validation. Always validate that a UUID is well-formed before using it in a query. A malformed UUID from a client can cause parse errors or, worse, inject unexpected characters. For generating test UUIDs, one-off IDs during development, or batch ID lists, the SnappyTools UUID Generator generates v4 UUIDs in-browser with no server round-trip. UUIDs solve a real problem — globally unique identifiers without coordination. UUID v4 is the safe default; UUID v7 is the better choice for database primary keys. Auto-increment remains the right answer when IDs are purely internal and sequential ordering matters.