Choose a UUID version
| Version | Construction | Typical reason to use it |
|---|---|---|
| v1 | Gregorian timestamp and node value | Compatibility with a legacy time-based system |
| v2 | Reserved for DCE Security | A specific legacy DCE requirement; not offered here |
| v3 | Name and namespace hashed with MD5 | Compatibility with an existing deterministic scheme |
| v4 | 122 random bits | General-purpose random identifiers |
| v5 | Name and namespace hashed with SHA-1 | Stable identifiers for the same inputs |
| v6 | Reordered v1 timestamp layout | Migration from v1 where that layout matters |
| v7 | Unix millisecond timestamp and random/counter fields | New time-ordered identifier designs |
| v8 | Application-defined payload with required version/variant bits | An explicitly specified custom scheme |
UUID v6 is standardised, not deprecated. RFC 9562 generally recommends v7 over v1 or v6 when possible. A v8 value needs its own layout documentation before its payload can be interpreted.
Name-based UUIDs are deterministic, not encrypted. SHA-1-based v5 does not provide a general authentication or cryptographic integrity mechanism. Browser-generated v1 values on FastUUID use a random node value; other implementations may use a hardware address.
Generate an identifier
In JavaScript and modern Node.js, native Web Crypto can generate v4:
const id = crypto.randomUUID();For v7 or v5, use a maintained UUID library:
import { v7, v5 } from 'uuid';
const ordered = v7();
const named = v5('example.com', v5.DNS);Python offers v4 and v5 in its standard library. Python 3.14 adds v6, v7, and v8:
import uuid
random_id = uuid.uuid4()
named_id = uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
# Python 3.14 or later:
ordered_id = uuid.uuid7()Check runtime requirements in the Python UUID documentation and uuid JavaScript documentation.
Inspect before interpreting
A canonical UUID has 32 hexadecimal digits grouped as 8-4-4-4-12. Uppercase and lowercase are equivalent. The version and variant determine how to interpret the bits. Nil and Max are special reserved values.
Use the validator to distinguish recognised layouts from reserved values, and the decoder to extract v1, v6, or v7 timestamps. An embedded timestamp is not proof of creation time or authenticity.
Store according to the database
Use PostgreSQL's native uuid type. PostgreSQL 18 provides native uuidv7() and UUID timestamp extraction; older PostgreSQL releases differ, so check the versioned PostgreSQL documentation.
In MySQL, binary UUID storage uses BINARY(16) with explicitly documented conversion conventions. Byte order and optional v1-oriented swaps must agree on writes and reads; do not assume every UUID version needs the same reordering.
Preserve all 128 bits. The binary/Base64 converter uses canonical network byte order; Microsoft's binary GUID conventions can differ. Encoding the same bits into Base58 changes the representation, not the entropy.
Common mistakes
- Treating UUIDs as API keys, passwords, or authorisation checks.
- Calling a successful sample-uniqueness test a proof that collisions cannot occur.
- Truncating values and continuing to assume 122 random bits.
- Expecting repeated v5 inputs or repeated Nil generation to produce distinct IDs.
- Treating timestamps as a total order across machines with different clocks.
- Assuming a database performance result applies to every schema and workload.
The collision calculator models independent uniform v4 values. It does not model every identifier scheme.
Standards reference
RFC 9562 supersedes RFC 4122 and defines UUID v6, v7, and custom v8 layouts. Reviewed on 10 September 2026; the original publication date and URL are retained.
Check your implementation
Use the UUID examples and test vectors to verify versions, v7 timestamps and canonical byte order. Download the fixed fixtures for repeatable tests; generate fresh identifiers for production records.
