UUID Generator
Generate universally unique identifiers (UUIDs) for your applications. Support for multiple UUID versions and bulk generation.
🔑UUID/GUID Generator
No UUIDs generated yet
UUID Validator
About UUIDs
UUID v4 (Random)
- • 122 random bits
- • Most commonly used
- • Cryptographically random
- • No privacy concerns
UUID v1 (Time-based)
- • Contains timestamp
- • MAC address based
- • Sortable by creation time
- • Privacy considerations
Example: 550e8400-e29b-41d4-a716-446655440000
What is a UUID?
A UUID (Universally Unique Identifier) is a 128-bit identifier used to uniquely identify information in computer systems. UUIDs are standardized by the Open Software Foundation (OSF) and are designed to be unique across space and time.
UUIDs are typically represented as 32 hexadecimal digits, displayed in five groups separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters (including hyphens).
UUID Versions
- •Version 1: Time-based, includes MAC address
- •Version 2: DCE Security (rarely used)
- •Version 3: Name-based using MD5 hash
- •Version 4: Random or pseudo-random (most common)
- •Version 5: Name-based using SHA-1 hash
Common Use Cases
- •Database Keys: Primary keys in distributed databases
- •API Resources: Unique identifiers for REST APIs
- •File Systems: Unique file and directory names
- •Session IDs: Unique session identifiers
- •Transaction IDs: Unique transaction tracking
Programming Examples
JavaScript
crypto.randomUUID()Python
import uuid
uuid.uuid4()Java
UUID.randomUUID()UUID Format Explained
550e8400-e29b-41d4-a716-446655440000Time Low
8 hex digits
Time Mid
4 hex digits
Time Hi & Version
4 hex digits
Clock Seq
4 hex digits
Node
12 hex digits
How UUID Generation Works
The Mathematics and Structure of UUIDs
A UUID (Universally Unique Identifier) is a 128-bit number, typically represented as 32 hexadecimal digits displayed in five groups separated by hyphens: 8-4-4-4-12 (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). The 128-bit space provides 2^128 ≈ 3.4×10^38 possible UUIDs. To put this in perspective, generating one billion UUIDs per second would take 10 trillion years before reaching a 50% probability of a single collision. This astronomical number space makes UUIDs effectively unique for practical purposes.
The UUID format includes version and variant fields that identify how the UUID was generated. Bits 48-51 encode the version (1-5), and bits 64-65 encode the variant (usually 10 for RFC 4122 UUIDs). These reserved bits reduce the actual randomness space, but the remaining 122 bits still provide sufficient uniqueness. The hyphenated format improves human readability—comparing "550e8400-e29b-41d4-a716-446655440000" is easier than "550e8400e29b41d4a716446655440000."
Version 4 UUIDs (random) are most common. They use 122 random bits, making collision probability negligible for most applications. The birthday paradox applies: with N possible values, you need approximately sqrt(N) samples before collision probability reaches 50%. For 122-bit space, that's 2^61 ≈ 2.3 quintillion UUIDs. Generating a trillion UUIDs per second would take 73 years to reach 50% collision probability—far exceeding any practical system's lifetime and scale.
UUID comparison and sorting work lexicographically in their string representation. "550e8400-..." sorts before "650e8400-..." because '5' < '6'. Database systems often store UUIDs in binary format (16 bytes) rather than strings (36 bytes) for efficiency. Binary storage saves space and accelerates comparisons—16-byte binary comparison is faster than 36-character string comparison. Indexing UUIDs requires careful consideration: random UUIDs create poor locality, leading to index fragmentation in B-trees.
UUIDs are case-insensitive—both uppercase and lowercase hex digits are valid, though lowercase is standard. Converting between formats (string to binary, binary to string) requires hexadecimal encoding/decoding. Most UUID libraries provide these conversions. Some systems use base64 encoding for more compact string representation (22 characters instead of 36), trading human readability for brevity in URLs or constrained contexts.
UUID Versions and Their Evolution
Version 1 UUIDs combine timestamp and MAC address. They encode the current time in 100-nanosecond intervals since October 15, 1582 (Gregorian calendar adoption), and append the network card's MAC address. This guarantees uniqueness across time and space—same machine can't generate duplicate UUIDs, and different machines have different MAC addresses. However, V1 reveals information: you can extract when and where the UUID was created, raising privacy concerns. Web applications rarely use V1 for this reason.
Version 2 UUIDs (DCE Security) are similar to V1 but replace timestamp bits with local domain identifier and user ID. These are rarely used outside specific distributed computing environments. Most UUID libraries don't even implement V2. Their specialized nature and privacy concerns (exposing user IDs) limited adoption. Modern systems needing similar functionality use custom solutions rather than relying on this underspecified UUID version.
Version 3 and Version 5 are name-based UUIDs. They hash a namespace UUID plus a name string, producing deterministic UUIDs—the same namespace and name always yield the same UUID. V3 uses MD5 (now considered weak), V5 uses SHA-1 (stronger). These enable consistent ID generation: convert "user@example.com" to a UUID deterministically. This is useful for generating stable IDs from natural keys or creating reproducible test data. The namespace UUID prevents collisions when different systems generate UUIDs from the same names.
Version 4 UUIDs are purely random (or pseudo-random). They're the simplest and most popular: generate 122 random bits, set the version and variant bits, format as hexadecimal. No timestamp, no MAC address, no name—just randomness. This simplicity makes them easy to implement and free of privacy concerns. The randomness should come from a cryptographically secure random number generator (CSPRNG) to ensure unpredictability and proper distribution across the UUID space.
Proposals for Version 6 and 7 UUIDs aim to address V4's database indexing problems. These new versions incorporate timestamps in a way that maintains sortability—UUIDs generated later have higher values. This improves database performance because sequential inserts cluster together in B-tree indexes. V6 reorders V1's timestamp for better lexicographic sorting. V7 uses Unix epoch timestamps for broader compatibility. As of 2024, these are still draft specifications, but adoption is growing in systems where UUID index performance matters.
Implementation and Random Number Generation
Generating cryptographically secure random UUIDs requires proper entropy sources. Operating systems provide CSPRNGs: /dev/urandom on Linux, CryptGenRandom on Windows, crypto.getRandomValues() in browsers. These APIs gather entropy from hardware events (keyboard timing, mouse movements, disk I/O timing) and use cryptographic algorithms to produce unpredictable random data. Never use language built-in random functions like Math.random() for UUID generation—they're predictable and can produce collisions.
UUID generation performance varies by source. Cryptographic RNGs are slower than PRNGs but necessary for security. Generating millions of UUIDs requires efficient implementations. Some systems batch entropy reads: request 1024 random bytes from the OS, use them to generate 64 UUIDs (16 bytes each), then request more. This amortizes the syscall overhead. Server applications generating high UUID volumes might use hardware RNGs if available, which provide faster entropy generation than software approaches.
UUID libraries handle version and variant bit setting automatically. After generating random bytes, they set specific bits: bits 48-51 to 0100 (version 4), bits 64-65 to 10 (RFC 4122 variant). This is done via bitwise operations: byte[6] = (byte[6] & 0x0F) | 0x40 sets the version, byte[8] = (byte[8] & 0x3F) | 0x80 sets the variant. These operations are cheap—generating the random bits dominates the computation time. The formatting step (converting to hex string with hyphens) is similarly fast.
Validation ensures UUIDs conform to spec. A valid UUID has correct length (36 characters with hyphens, 32 without), hyphens in correct positions, valid hex digits, and proper version/variant bits. Libraries provide validation functions. When accepting UUIDs from external sources (APIs, user input), validation prevents injection attacks and ensures data integrity. Invalid UUIDs should be rejected early to avoid propagating malformed data through the system.
Nil UUID (00000000-0000-0000-0000-000000000000) is reserved to represent absence of a UUID, similar to null in programming. Some systems use it as a default value. Testing UUID code requires deterministic generation for reproducibility. Test libraries often allow seeding the RNG or providing fixed UUID values. Production code should never use predictable UUID generation—tests are the only exception where reproducible UUIDs are desirable.
Database Considerations and Performance
Storing UUIDs as primary keys has tradeoffs. Random UUIDs cause poor index locality—each insert may update a different B-tree page, preventing page caching and causing more disk I/O. Sequential integer IDs insert at the end of the index, enabling efficient caching. For high-write systems, this performance difference is significant. Some databases provide UUID types that store values in binary, saving space and improving comparison speed. PostgreSQL has a native uuid type. MySQL typically uses char(36) or binary(16).
Index fragmentation from random UUIDs degrades performance over time. B-tree indexes work best with sequential inserts. Random UUIDs fill the index randomly, requiring frequent page splits and rebalancing. This increases write amplification and slows queries. Solutions include using sequential UUID variants (V6/V7), storing UUIDs in non-primary-key columns, or using hybrid approaches: sequential integers as primary keys with UUIDs as unique secondary indexes for external references.
JOIN performance on UUID columns is slower than integers because UUIDs are larger. A 16-byte binary UUID takes twice the memory of an 8-byte bigint. This matters for in-memory joins and temporary tables—more memory per row means fewer rows fit in memory, causing disk spills. For systems with billions of rows and complex joins, this overhead accumulates. Index size grows proportionally—a table with UUID primary key has larger indexes than equivalent integer-keyed tables.
Partitioning strategies with UUIDs require careful planning. Random UUIDs don't partition well by range—every partition receives roughly equal inserts. This can be desirable for even load distribution but prevents time-based partitioning (archiving old data). Sequential UUID variants (V1, V6, V7) enable time-based partitioning since they incorporate timestamps. Hash partitioning works with any UUID version and distributes rows evenly across partitions.
Replication and distributed systems benefit from UUIDs. When multiple databases generate IDs independently, UUIDs prevent collisions without coordination. Traditional auto-increment IDs require centralized ID generation or complex coordination protocols. UUIDs allow each node to generate IDs independently. This simplifies multi-master replication, offline-first applications, and microservices architectures where multiple services create entities that eventually merge into a central database.
Security and Privacy Implications
UUIDs are not secrets. Their unpredictability comes from the vast number space, not cryptographic strength. Knowing one UUID doesn't help predict the next. However, using UUIDs in URLs as authorization tokens is dangerous—if an attacker can enumerate UUIDs or guess them, they access unauthorized resources. For security-sensitive references, use proper authentication and authorization, not URL obscurity. UUIDs work as identifiers but not as access control mechanisms.
Version 1 UUIDs leak information: timestamp reveals when the UUID was created, MAC address reveals where. This enables tracking users or systems over time. If privacy matters, use V4 (random) UUIDs instead. The MAC address exposure can reveal system identity—attackers gathering V1 UUIDs from an API can correlate them to specific machines, potentially aiding reconnaissance. In privacy-conscious applications, V1 is inappropriate.
Timing attacks on UUID generation are theoretical but possible. If UUID generation time varies based on internal state, attackers measuring generation latency might extract information. Constant-time UUID generation prevents this. In practice, UUID generation is fast enough that timing variations are negligible, and the security risk is minimal. However, security-critical systems should use UUID libraries audited for side-channel resistance.
Sequential UUIDs (V1, V6, V7) enable enumeration attacks. If UUIDs increment predictably, attackers can guess valid UUIDs: given UUID N, try N+1, N+2, etc. This allows enumerating resources that should be private. Random V4 UUIDs resist enumeration because guessing the next UUID is computationally infeasible. Systems exposing UUIDs in URLs should use V4 and implement rate limiting to prevent brute-force attacks, though the UUID space is large enough to make brute force impractical.
UUID v4 collision handling requires careful consideration. While collisions are astronomically unlikely, production systems should handle them gracefully. Database unique constraints on UUID columns cause insert failures if collisions occur. The application should catch these errors and retry with a new UUID. In practice, properly implemented UUID generation makes collisions so rare that most systems will never encounter one. However, defensive programming includes collision handling—even if the probability is one in a trillion.
Language-Specific Implementations and Best Practices
JavaScript provides crypto.randomUUID() in modern browsers and Node.js (v14.17+). This generates V4 UUIDs using the platform's CSPRNG. For older environments, the uuid npm package provides comprehensive UUID support: v1, v3, v4, v5 generation, parsing, and validation. The package is well-tested and used by millions of projects. Usage: import { v4 as uuidv4 } from 'uuid'; const id = uuidv4(); Simple and reliable.
Python's uuid module is part of the standard library. uuid.uuid4() generates V4 UUIDs, uuid.uuid1() generates V1, uuid.uuid3() and uuid.uuid5() handle name-based UUIDs. The module automatically uses the OS's CSPRNG. For high-performance applications, consider the secrets module combined with manual UUID formatting, though the standard uuid module suffices for most cases. Python's UUID objects support comparison, hashing, and serialization.
Java provides java.util.UUID with randomUUID() for V4 generation. UUID.fromString() and toString() handle parsing and formatting. Java UUIDs are comparable and hashable, working well as map keys. The implementation uses java.security.SecureRandom for cryptographic-quality randomness. For Android, the same API is available. Java's UUID type is widely used in enterprise applications, Hibernate ORM supports it natively, and JDBC drivers handle UUID columns efficiently.
Go's github.com/google/uuid package is the standard choice. uuid.New() generates V4 UUIDs. The package supports all UUID versions, provides parsing/formatting, and includes validation. Go's database/sql package works with UUIDs when using drivers that support them. For PostgreSQL, use github.com/lib/pq with UUID columns. Go's uuid package uses crypto/rand for secure random generation, ensuring unpredictability.
Best practices across languages: use UUID libraries rather than rolling your own—UUID generation has subtle requirements. Store UUIDs in binary format in databases when possible. Use V4 for general purposes, V5 for name-based generation, avoid V1 unless you need timestamps. Include UUID validation when accepting external input. Test UUID generation code with collision detection (even though collisions should never occur). Document which UUID version you use and why—this helps future maintainers understand the design decisions.
FAQ
Can two UUID v4 generators create the same UUID?
Theoretically yes, but the probability is so infinitesimally small it's effectively impossible. UUID v4 has 122 random bits, providing 2^122 ≈ 5.3 × 10^36 possible values. You'd need to generate trillions of UUIDs per second for millennia before having a realistic chance of collision. In practice, if you encounter duplicate UUIDs, it's due to faulty random number generation, not chance collision.
Should I use UUIDs or auto-increment integers as primary keys?
It depends on your use case. Integers are faster and more efficient for databases with heavy writes and complex joins. UUIDs are better for distributed systems, preventing conflicts in multi-master replication, offline-first apps, and when you need globally unique IDs without coordination. For simple single-database applications, integers often perform better. For distributed architectures or when you need to generate IDs client-side, UUIDs are superior.
Why do some systems use shorter IDs than full UUIDs?
Services like URL shorteners use shorter IDs (6-8 characters) because full UUIDs (36 characters) are unwieldy in URLs. They use base62 or base64 encoding with fewer bits (48-64 bits instead of 128), accepting higher collision probability in exchange for brevity. For URL shorteners handling millions (not billions) of URLs, 64-bit IDs provide sufficient uniqueness. These aren't UUIDs—they're custom ID schemes optimized for specific use cases.
Can I sort or order records by UUID?
You can sort UUIDs lexicographically, but random UUID v4 values have no meaningful order—they're random by design. Sorting by UUID gives arbitrary order, not chronological or logical order. If you need sortable UUIDs, use UUID v1 (includes timestamp) or newer v6/v7 proposals (designed for sortability). For most applications, add a separate created_at timestamp column if you need chronological ordering, and keep UUIDs for identification only.