UUID Guide: What They Are and How to Generate Them

If you have ever designed a database schema, built a REST API, or worked with microservices, you have almost certainly encountered UUIDs. These 128-bit identifiers appear as seemingly random strings of hexadecimal characters, yet they solve one of the most fundamental problems in distributed computing: generating unique identifiers without a central authority. This guide explains what UUIDs are, walks through the major versions, and covers when and how to use them effectively.

What Is a UUID?

A UUID (Universally Unique Identifier) is a 128-bit value standardized by RFC 9562 (which superseded the original RFC 4122). UUIDs are sometimes called GUIDs (Globally Unique Identifiers) in the Microsoft ecosystem — they are the same thing.

A UUID is represented as 32 hexadecimal digits separated by hyphens in five groups, following the pattern 8-4-4-4-12:

550e8400-e29b-41d4-a716-446655440000

The key insight behind UUIDs is that the space of possible values is so astronomically large (2128, or roughly 3.4 × 1038) that independently generated UUIDs are virtually guaranteed to be unique without any coordination between the systems producing them. This property makes UUIDs invaluable in distributed architectures where a centralized sequence generator would be a bottleneck or a single point of failure.

UUID Versions Explained

Not all UUIDs are created equal. The version number (encoded in the 13th character of the string) determines how the UUID was generated and what guarantees it provides. Here are the versions you need to know:

Version 1: Timestamp + MAC Address

UUIDv1 combines a 60-bit timestamp (100-nanosecond intervals since October 15, 1582) with the MAC address of the generating machine. This means v1 UUIDs are naturally sortable by creation time and are guaranteed unique per machine. However, embedding the MAC address raises privacy concerns — anyone who reads the UUID can identify the hardware that generated it. For this reason, v1 is rarely used in modern applications.

Version 4: Random

UUIDv4 is by far the most widely used version. It fills 122 of the 128 bits with cryptographically random data (the remaining 6 bits encode the version and variant). Generation is trivially simple — just call your language's random UUID function:

// JavaScript (Node.js or browser)
crypto.randomUUID();
// → "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed"

// Python
import uuid
str(uuid.uuid4())
// → "6ba7b810-9dad-4d13-8f0b-67f92cb05e74"

// Command line (Linux/macOS)
uuidgen

The probability of a collision with v4 is vanishingly small. You would need to generate approximately 2.71 × 1018 UUIDs (2.71 quintillion) to have a 50% chance of a single collision. For all practical purposes, every v4 UUID is unique.

Version 5: Name-Based (SHA-1)

UUIDv5 generates a deterministic UUID from a namespace UUID and a name string by hashing them with SHA-1. Given the same namespace and name, you will always get the same UUID. This is useful when you need reproducible identifiers — for example, generating a stable UUID for a URL or a DNS name:

// Python — UUID v5 from a URL
import uuid
ns = uuid.NAMESPACE_URL
print(uuid.uuid5(ns, "https://tensorlocal.com"))
// → always produces the same UUID for this input

Version 3 is the older variant that uses MD5 instead of SHA-1. Prefer v5 over v3 since MD5 is considered cryptographically broken.

Version 7: Unix Timestamp + Random (The New Standard)

UUIDv7 is the newest and most exciting version, introduced in RFC 9562. It encodes a 48-bit Unix timestamp in milliseconds in the most significant bits, followed by random data. This design gives you the best of both worlds:

  • Sortability — UUIDv7 values sort chronologically when compared as strings or bytes, making them excellent database primary keys that maintain insertion order.
  • Randomness — The random component ensures uniqueness even when multiple UUIDs are generated in the same millisecond.
  • Privacy — Unlike v1, no hardware information is embedded.
  • Performance — B-tree indexes handle sequentially ordered keys far more efficiently than fully random ones, so v7 can significantly reduce index fragmentation compared to v4.
// UUIDv7 structure (conceptual)
|  48-bit timestamp  | ver |  12-bit rand  | var |  62-bit rand  |
| 0192a0b0-7c90     |  7  |   abc         |     |  rest...      |

// Example UUIDv7
0192a0b0-7c90-7def-8abc-1234567890ab

If you are starting a new project and need to pick a UUID version, UUIDv7 is the recommended default. It offers the best combination of uniqueness, sortability, and database performance.

UUID Use Cases

UUIDs appear everywhere in modern software. Here are the most common scenarios where they shine:

Database Primary Keys

Using UUIDs instead of auto-incrementing integers as primary keys eliminates the need for a centralized sequence. This is critical when you have multiple write replicas, sharded databases, or need to generate IDs on the client side before inserting into the database. UUIDv7 is particularly well-suited here because its time-ordered nature avoids the B-tree page-splitting problem that random v4 UUIDs cause in large tables.

Distributed Systems and Microservices

When multiple independent services need to create records that will eventually be merged, UUIDs guarantee that no two services will produce the same identifier. This eliminates an entire category of race conditions and coordination overhead.

API Resource Identifiers

Exposing auto-incrementing IDs in public APIs leaks information — users can estimate how many records exist and enumerate resources by incrementing the ID. UUIDs are opaque and non-sequential (with v4), making them a better choice for external-facing identifiers:

// Leaks information
GET /api/users/42
GET /api/users/43

// Opaque and secure
GET /api/users/550e8400-e29b-41d4-a716-446655440000

Idempotency Keys

When a client sends a request that might be retried (payment processing, order creation), attaching a UUID as an idempotency key allows the server to detect and deduplicate retries without processing the same operation twice.

Best Practices

Follow these guidelines to use UUIDs effectively in your projects:

  1. Prefer UUIDv7 for new projects. The time-ordered property improves database index performance dramatically while maintaining all the uniqueness guarantees of v4.
  2. Store UUIDs as binary (16 bytes) in databases, not as strings (36 characters). This cuts storage requirements by more than half and improves comparison performance. Most databases have a native UUID type — use it.
  3. Do not use UUIDs as security tokens. UUIDv1 and v7 contain timestamps, and even v4 values are not intended to be unguessable secrets. Use cryptographically secure random tokens for session IDs and API keys.
  4. Use lowercase hexadecimal with hyphens as the canonical string representation. While the spec says UUIDs are case-insensitive, consistently using lowercase avoids comparison bugs and looks cleaner in logs.
  5. Validate UUID format on input. When accepting UUIDs from external sources, verify the format matches the expected pattern before using them in queries. A simple regex works: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i

Need to generate UUIDs quickly? Try our free UUID Generator — supports v1, v4, and v7 with bulk generation.

Open UUID Generator →

UUID vs. Other Identifier Strategies

UUIDs are not the only option for unique identifiers. Here is how they compare to common alternatives:

  • Auto-increment IDs — Simple and space-efficient, but require a centralized sequence and leak ordering information. Best for single-database applications where external exposure is not a concern.
  • ULID — A 128-bit identifier with a 48-bit timestamp and 80 bits of randomness, encoded as a 26-character Crockford Base32 string. Lexicographically sortable like UUIDv7, but uses a more compact string representation. The downside is less ecosystem support than UUIDs.
  • Snowflake IDs — Twitter's approach uses 64 bits: a timestamp, a machine ID, and a sequence number. More compact than UUIDs and naturally sortable, but requires a machine ID registry to avoid collisions.
  • NanoID — A compact, URL-friendly random ID generator. Customizable alphabet and length. Useful for short, human-readable identifiers but lacks the standardization of UUIDs.

Conclusion

UUIDs are one of those foundational tools that every developer should understand. Whether you are designing a database schema, building a microservices architecture, or creating a public API, choosing the right identifier strategy has real implications for performance, security, and system design. UUIDv4 remains a solid general-purpose choice, but if you are starting fresh, UUIDv7 gives you the best combination of uniqueness, sortability, and database efficiency.

The next time you need a unique identifier, skip the debate and generate one instantly with the right version for your use case.