← Back to blog

What Is a UUID and When Should You Use One?

A UUID (Universally Unique Identifier) is a 128-bit identifier formatted as a 32-character hexadecimal string divided into five groups by hyphens, for example: 550e8400-e29b-41d4-a716-446655440000. UUIDs are designed to be unique across systems without a central coordinator, which makes them useful in distributed systems, offline-first applications, and public APIs where you do not want to expose sequential IDs.

UUID versions

The UUID specification defines several versions. Version 1 is time-based: it encodes the current timestamp and MAC address, which makes it sortable by creation time but leaks machine identity. Version 3 and Version 5 are name-based: they hash a namespace and name using MD5 or SHA-1 to produce a deterministic UUID. Version 4 is randomly generated — all bits except those encoding the version and variant are random.

Version 7 (RFC 9562, 2024) combines a millisecond-precision timestamp prefix with random bits, giving UUIDs that are both unique and naturally sortable by insertion time. This makes v7 preferable to v4 in database primary key scenarios where index fragmentation from random IDs is a concern.

When to use a UUID

UUIDs are a good default for primary keys in distributed databases, microservices, and any scenario where multiple independent sources generate records that must be merged without conflicts. They also prevent enumeration attacks — if user IDs are /users/1, /users/2, ..., anyone can scrape all records by incrementing the number. A UUID endpoint like /users/550e8400-... reveals nothing.

They are also useful as idempotency keys for API requests, as correlation IDs for distributed tracing, and as file names for uploaded assets where collision-free naming is needed without a database lookup.

Trade-offs vs. other ID strategies

The main downsides of version-4 UUIDs are size and randomness. At 36 characters (or 16 bytes binary), they are larger than a 4-byte integer, which increases index and storage overhead in databases with millions of rows. Random UUIDs also cause index fragmentation in B-tree databases (PostgreSQL, MySQL) because new values insert in unpredictable positions rather than at the end of the index.

Auto-increment integers are compact and cache-friendly but require a centralised sequence generator, expose record counts, and break in multi-master replication. UUID v7 and ULID (Universally Unique Lexicographically Sortable Identifier) are designed to keep the collision-resistance of UUIDs while restoring monotonic ordering for better index performance.

UUID v4 generation and uniqueness

UUID v4 generates 122 bits of randomness (6 bits are used for version and variant markers). The probability of two randomly generated UUIDs colliding is roughly 1 in 5.3 × 10^36 — effectively zero for any realistic workload. Generating one billion UUIDs per second for a century would still give a collision probability of only about 50%.

For a collision to matter in practice you would need to generate IDs at extreme scale within the same namespace, which is not a realistic concern for most applications. Our UUID generator uses the browser's Web Crypto API (crypto.randomUUID where available, falling back to crypto.getRandomValues) to ensure cryptographic-quality randomness rather than Math.random(), which is not suitable for security-sensitive identifiers.