Definition

The clock sequence is a field in time-based UUID formats that serves two purposes:

  1. Monotonic ordering — UUIDs generated within the same clock tick sort in generation order
  2. Clock adjustment safety — if the system clock moves backwards (NTP adjustment, leap second, VM migration), the clock sequence prevents generating a duplicate UUID with an older timestamp

The concept applies to UUID v1, v6, and v7, though the implementation details differ across versions. RFC 9562 consolidates the spec under the term “monotonic counter” for UUID v7. The Wikipedia UUID article — clock sequence section provides a concise overview of why this field exists.

Clock sequence in UUID v1 and v6

In UUID v1 and v6, the clock sequence is a 14-bit field stored in bits 64–77 (the first two bytes of the fourth group):

UUID v1 string: xxxxxxxx-xxxx-1xxx-[CSHigh][CSLow]xx-xxxxxxxxxxxx
                                    ^^^^^^^^^^^^^^^^
                                    CS = clock sequence (14 bits) + 2 variant bits

Example v1: 550e8400-e29b-11d4-a716-446655440000
                              ^^^^
                              a7 = 1010 0111 → variant=10, CS_hi=10 0111

The clock sequence is initialized to a random value at process startup. It increments:

With a 14-bit field, there are 16,384 possible clock sequence values, limiting UUID v1/v6 generators to 16,384 unique UUIDs per 100-nanosecond tick per process.

Clock sequence (monotonic counter) in UUID v7

UUID v7 replaces the 14-bit clock sequence with a 12-bit rand_a field (bits 52–63). RFC 9562 §6.2 describes three implementation methods:

Method 1 — Fixed-increment monotonic counter (recommended): The rand_a bits act as a counter. When the timestamp advances, rand_a is reset to a random value. When the timestamp is unchanged, rand_a increments by 1 (or a fixed random increment). This guarantees within-millisecond sort order:

Millisecond 1000:
  018fbe3a-4c5d-7000-8abc-0123456789ab  ← rand_a = 0x000
  018fbe3a-4c5d-7001-8abc-0123456789ac  ← rand_a = 0x001
  018fbe3a-4c5d-7002-8abc-0123456789ad  ← rand_a = 0x002

Millisecond 1001 (clock advances):
  018fbe3a-4c5e-7a3f-8abc-0123456789ae  ← rand_a reset to random 0xa3f

Method 2 — Random reseed per millisecond: rand_a is re-seeded from the CSPRNG on each clock tick. Within a millisecond, values are not ordered. Simpler to implement but no within-millisecond ordering.

Method 3 — Increment-then-use: Like Method 1, but the counter increments before use rather than after. Functionally equivalent; matters for the first UUID of each millisecond.

The uuid npm package implements Method 1 — the v7.ts source on GitHub shows the per-process counter reset logic exactly. PostgreSQL 18’s uuidv7() also uses Method 1, as documented in the PostgreSQL 18 UUID functions reference.

Clock rollback handling

If the system clock moves backwards — from an NTP correction, live VM migration, or manual adjustment — a naive implementation would generate UUID v7 values with a timestamp smaller than the last-used timestamp. These would sort before recently generated UUIDs, violating the monotonic ordering property.

The correct response is to hold the last-seen timestamp and continue incrementing the counter until the clock catches up:

// Pseudo-code — simplified monotonic counter with rollback protection
let lastMs = 0n;
let counter = 0;

function generateV7() {
    const nowMs = BigInt(Date.now());

    if (nowMs > lastMs) {
        lastMs = nowMs;
        counter = Math.floor(Math.random() * 0x1000);  // reset counter
    } else {
        // Clock same or moved back — keep lastMs, increment counter
        counter = (counter + 1) & 0xfff;
        if (counter === 0) {
            // Counter overflow — advance lastMs artificially
            lastMs += 1n;
        }
    }

    // Construct UUID v7 from lastMs and counter
    return buildUUIDv7(lastMs, counter);
}

This ensures monotonic output even across NTP adjustments. RFC 9562 §6.2 calls this “freeze the timestamp and increment the counter.” For a deep dive on clock skew in distributed systems, see the Wikipedia article on clock synchronization.

Bit layout comparison

VersionField nameBitsLocation
v1clock_seq14Bits 64–77 (4th group first byte)
v6clock_seq14Bits 64–77 (4th group first byte)
v7rand_a (monotonic counter)12Bits 52–63 (end of 3rd group)

UUID v7 uses 2 fewer bits for the counter because it does not need to protect against sub-millisecond clock rollback — millisecond precision is sufficient for its ordering guarantees.

Generate a UUID v7 with a live monotonic counter in the UUID v7 generator.

External references

Frequently asked questions

What is the clock sequence in a UUID?

The clock sequence is a counter field used in time-based UUIDs (v1, v6, v7) to prevent collisions when two UUIDs are generated within the same clock tick or when the system clock is set backwards. In UUID v1 and v6 it is 14 bits; in UUID v7 the equivalent field (rand_a, bits 52–63) is 12 bits and is called a monotonic counter or sequence counter. See RFC 9562 §6.2 for the monotonic counter specification.

Why does UUID need a clock sequence if each UUID has random bits?

Random bits alone would give any two same-millisecond UUIDs non-deterministic relative order. A monotonic counter guarantees that UUIDs generated in sequence within the same millisecond also sort in generation sequence — important for audit logs, event streams, and B-tree index efficiency. Without it, an application generating 10,000 UUIDs per second (10 per millisecond) would have no ordering guarantee within each millisecond window.

Does UUID v7 have a clock sequence field?

UUID v7 has a 12-bit rand_a field (bits 52–63) that RFC 9562 §6.2 recommends using as a monotonic counter. This is functionally equivalent to the clock sequence in v1/v6. A well-implemented UUID v7 generator increments this counter for each UUID generated within the same millisecond and resets it when the clock advances.