A time-based UUID embeds a timestamp so that values generated later sort after values generated earlier. Three UUID versions include a timestamp: v1, v6, and v7. Only v7 is recommended for new work.

UUID v1 (Deprecated)

UUID v1 was the original time-based format, defined in RFC 4122 (2005) and deprecated by RFC 9562 (2024).

Bit layout:

time_low     (32 bits) — low 32 bits of 60-bit timestamp
time_mid     (16 bits) — middle 16 bits of timestamp
time_hi_ver  (16 bits) — high 12 bits + 4-bit version (1)
clock_seq    (14 bits) — sequence number + 2-bit variant
node         (48 bits) — MAC address or random bytes

Problems with v1:

  1. The timestamp fragments are stored in a non-sequential field order — sorting v1 UUIDs lexicographically does NOT give chronological order
  2. The node field originally contained the host MAC address — a machine fingerprint and privacy leak
  3. The 100-nanosecond epoch (October 15, 1582) is unusual and error-prone

Generating v1 (only for legacy compatibility):

import uuid
# uuid.uuid1() still works but is deprecated for new use
legacy_id = uuid.uuid1()

UUID v6 (Reordered v1)

UUID v6 reorders the timestamp fields from v1 so the UUID is lexicographically sortable — the most significant bits come first:

time_high (32 bits) — high 32 bits of 60-bit timestamp
time_mid  (16 bits) — middle 16 bits
time_low  (12 bits) — low 12 bits (after version nibble)
version   (4 bits)  — always 6
clock_seq (14 bits) — monotonic counter
variant   (2 bits)  — always 10
node      (48 bits) — MAC or random

v6 is a migration path for systems already on v1 — it is sortable, but still uses the same 1582 epoch and the node field. Prefer v7 for all new work.

UUID v7 uses a clean Unix millisecond timestamp in the high 48 bits:

unix_ts_ms (48 bits) — Unix time in milliseconds
version    (4 bits)  — always 7
seq_hi     (12 bits) — monotonic counter or random
variant    (2 bits)  — always 10
rand_b     (62 bits) — cryptographically random

Why v7 wins:

import { v7 as uuidv7 } from 'uuid';
const id = uuidv7(); // 018fbe3a-4c5d-7b12-8abc-0123456789ab
import uuid
id = uuid.uuid7()  # Python 3.13+

Extracting the v7 Timestamp

function uuidV7ToDate(uuid) {
  const ms = parseInt(uuid.replace(/-/g, '').slice(0, 12), 16);
  return new Date(ms);
}

uuidV7ToDate('018fbe3a-4c5d-7b12-8abc-0123456789ab');
// → 2024-05-21T...

Version Comparison Table

Featurev1v6v7
Timestamp epoch1582 (Gregorian)1582 (Gregorian)1970 (Unix)
Timestamp precision100 ns100 ns1 ms
Lexicographically sortableNoYesYes
Contains MAC addressYes (default)Yes (default)No
RFC 9562 statusDeprecatedNot deprecatedRecommended
Random bits141474

Frequently asked questions

What is a time-based UUID?

A time-based UUID embeds a timestamp so values generated later sort after values generated earlier. UUID v1 (deprecated) uses a 60-bit 100ns timestamp and MAC address. UUID v6 reorders v1's fields for sortability. UUID v7 (recommended) uses a 48-bit Unix millisecond timestamp with no MAC address and 74 bits of randomness. RFC 9562 recommends v7 for all new work.

What is a UUID v7 monotonic counter?

A monotonic counter is a per-millisecond integer that some UUID v7 generators use to keep successive UUIDs in creation order even within the same millisecond. RFC 9562 §6.2 recommends it but does not require it. The uuid npm package implements a counter; Python 3.13's uuid.uuid7() does not.

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 a time-based UUID?

A time-based UUID embeds a timestamp in the UUID's bits so that values sort in approximate creation order. UUID v1 was the original time-based version — it uses a 60-bit 100-nanosecond timestamp and optionally includes the host MAC address (a privacy leak). RFC 9562 defines UUID v7 as the modern replacement — it uses a 48-bit Unix millisecond timestamp with no MAC address.

Should I use UUID v1 or UUID v7?

Always use UUID v7 for new work. RFC 9562 explicitly deprecates UUID v1, citing the MAC address privacy leak and the non-lexicographic timestamp ordering. UUID v7's 48-bit Unix millisecond timestamp is simpler, sorts correctly as a string, and is supported natively in PostgreSQL 18, Python 3.13, and all major UUID libraries.