RFC 9562, published in May 2024, introduced three new UUID versions alongside the widely discussed v7. UUID v8 is the least prescribed of the three — only 6 bits are fixed by the standard, leaving 122 bits for the application to define. This makes it the escape hatch for use cases that do not fit v4 or v7.
What RFC 9562 Specifies for v8
The version nibble at bits 76–79 must be 1000 (hex 8), and the variant bits at bits 64–65 must be 10 (RFC 4122 variant). Everything else — all 122 remaining bits — is application-defined. The standard explicitly states that the internal layout is not interoperable across implementations unless separately documented.
When to Use UUID v8
UUID v8 makes sense when you need to:
- Embed a non-standard timestamp: A nanosecond or microsecond timestamp, a custom epoch, or a Tai64 timestamp rather than Unix milliseconds.
- Encode shard or region metadata: Embed a datacenter ID, shard key, or geographic region in the high bits for routing purposes.
- Adopt an existing proprietary format: Systems that already have a 128-bit ID format (e.g., Snowflake, KSUID) can re-encode values as UUID v8 to expose them through UUID-typed columns and APIs without changing the data.
- Versioned identifiers: Embed a schema version into the ID itself, useful for self-describing records in append-only event stores.
A Practical Layout Example
A common UUID v8 layout for high-throughput services:
| Bits | Width | Content |
|---|---|---|
| 0–47 | 48 bits | Unix timestamp (milliseconds) |
| 48–51 | 4 bits | Version (1000 = 8) |
| 52–63 | 12 bits | Shard ID (0–4095) |
| 64–65 | 2 bits | Variant (10) |
| 66–127 | 62 bits | Random bits |
This layout gives millisecond time-ordering (like v7) while also embedding a shard ID for routing — something v7 does not support without out-of-band metadata.
UUID v8 in Practice
No standard library generates UUID v8 automatically — by definition the layout must be custom. Generation requires manual bit manipulation:
function uuidV8(shardId) {
const ms = BigInt(Date.now());
const rand = crypto.getRandomValues(new Uint8Array(8));
const randBig = rand.reduce((acc, b) => (acc << 8n) | BigInt(b), 0n);
// version nibble = 8 at bits 76-79, variant = 0b10 at bits 64-65
const high = (ms << 16n) | 0x8000n | BigInt(shardId & 0xfff);
const low = (0x8000000000000000n) | (randBig & 0x3fffffffffffffffn);
const hex = high.toString(16).padStart(16, '0') + low.toString(16).padStart(16, '0');
return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`;
}
Interoperability Considerations
UUID v8 values are valid UUIDs — any system that accepts a UUID string will store and return a v8 value without error. However, the meaning of the bits is opaque to consumers unless the layout is documented. If you expose UUID v8 identifiers in a public API, document the bit layout in your API reference so consumers can extract embedded metadata if needed.
For internal systems where all consumers share the same codebase, UUID v8 is a clean way to pack more information into an ID without a separate metadata field.
Related Resources
- RFC 9562 §5.8 — UUID v8 specification
- Timeflake — a UUID-compatible 128-bit ID with custom timestamp precision
- ULID specification — alternative sortable ID format that inspired parts of UUID v7 design
Frequently asked questions
What is UUID v8 and when should I use it?
UUID v8 is a custom-layout UUID defined by RFC 9562 §5.8. Only the version nibble (4 bits) and variant bits (2 bits) are specified — the remaining 122 bits are application-defined. Use it when you need to embed custom metadata (shard IDs, region codes, non-standard timestamps) in an ID while keeping the standard UUID format and column type.
What did RFC 9562 add to the UUID standard?
RFC 9562, published in May 2024, adds UUID v6 (reordered timestamp for sortability), v7 (Unix millisecond timestamp), and v8 (custom layout). It also defines the Max UUID sentinel (all-ones complement of the Nil UUID) and deprecates v1 and v2. The existing format and v3, v4, v5 semantics are unchanged.
Should I use v4 or v7?
Use v7 for database primary keys (time-sortable, index-friendly) and v4 for anything where creation order could leak information, like tokens or share links.
What is UUID v8 used for?
UUID v8 is a "custom" UUID layout defined by RFC 9562 §5.8. Only the version nibble (4 bits) and the variant bits (2 bits) are fixed by the standard — the remaining 122 bits are application-defined. This makes it suitable for encoding domain-specific data like shard IDs, region codes, or custom timestamps while remaining a valid RFC UUID.
How is UUID v8 different from UUID v7?
UUID v7 has a fixed structure — 48-bit Unix millisecond timestamp, version nibble, 12-bit sequence, variant bits, and 62 random bits. UUID v8 has no prescribed structure beyond the version and variant fields; the layout is entirely up to the application. v7 is the right default for time-ordered IDs; v8 is for teams that need a non-standard layout but want RFC compliance.