UUIDv7 Guarantees Uniqueness and Little Else, and Python 3.14's Generator Kept Running Ahead of a Reset Clock
Software / explainer
UUIDv7 Guarantees Uniqueness and Little Else, and Python 3.14's Generator Kept Running Ahead of a Reset Clock
Robert Alexander's Oct. 19 post sets RFC 9562's own wording against the ordering, timestamp and unguessability assumptions developers make.
A UUIDv7 guarantees uniqueness and little else, according to a post by Robert Alexander dated Oct. 19 that was submitted to Lobsters on Oct. 22. Time ordering, an accurate embedded timestamp and unguessability are properties developers assume, and the post argues the standard promises none of them.
The standard is RFC 9562, published in May 2024 by K. Davis of Cisco Systems, B. Peabody of Uncloud and P. Leach of the University of Washington. It obsoletes RFC 4122.
What a UUIDv7 actually contains
Section 5.7 of RFC 9562 allocates a Unix timestamp in milliseconds to the top 48 bits. A 4-bit version field follows, then 12 bits called rand_a and a final 62 bits called rand_b, after a 2-bit variant field.
That layout is why databases like the type: IDs created later sort later, so B-tree indexes see mostly appends. Postgres, whose documentation Alexander quotes, warns that "the extracted timestamp is not necessarily exactly equal to the time the UUID was generated."
Where the guarantees stop
Alexander walks through four assumptions, and the RFC text he cites supports each gap.
| Assumption | What RFC 9562 says | Source section |
|---|---|---|
| The timestamp is the creation time | "Implementations MAY alter the actual timestamp" | 6.1 |
| IDs always sort in creation order | Implementations "SHOULD check" the new UUID is greater than the last | 6.2 |
| The ID is hard to guess | "SHOULD NOT assume that UUIDs are hard to guess" | 8 |
| An ID can act as a credential | "MUST NOT be used as security capabilities" | 8 |
The RFC says counter rollovers "MUST be handled by the application to avoid sorting issues," and its minimum counter is 12 bits. Alexander calculates that overflow takes more than 4,096 IDs per millisecond on one node.
On ordering across machines, he notes that Lamport showed clocks cannot be synchronised precisely enough for it. Even on one node, a millisecond timestamp with no counter can emit out-of-order IDs inside a tight loop, as an issue on the pg_uuidv7 project shows.
The Python 3.14 test that drifted past 3,600 seconds
The sharpest evidence is a test of Python 3.14's uuid.uuid7(). Alexander set the system clock back one hour and generated 100,000 IDs per loop. The embedded timestamp's delta from real time started at -0.000748 seconds, then read 3,695.28, 3,795.04, 3,894.81 and 3,994.57 seconds across successive loops.
The expected delta was about 3,600 seconds, the hour the clock had been set back. Instead the gap kept growing by roughly 100 seconds per loop, because the generator advances its own timestamp ahead of the system clock when it runs out of counter space. At more than one ID per millisecond, he says, the gap grows without bound; at lower rates the system clock eventually catches up.
CPython's developers, in issue #138862, argued the behaviour is consistent with the RFC and with other implementations. Alexander agrees it matches other implementations but wishes they handled clock jumps better, citing a Telstra incident with a clock "even decades out of sync" and a 2023 Windows clock reset.
He also found no implementation that persists the last timestamp, which the RFC's approach needs across restarts. A restart after a backward clock jump can therefore produce out-of-order IDs.
What to check before choosing it
Alexander's guidance is six questions about whatever library generates the IDs: whether it is RFC compliant, what extra properties it guarantees, what limits apply, what it assumes about the clock, when it alters the timestamp, and how guessable the IDs are.
One leak is simpler. An ID shared without its timestamp still exposes one, possibly high-precision, so a profile URL built on a UUIDv7 reveals when the account was created. Alexander ranks that low among the problems he sees in security assessments, but says it matters in some contexts.
His conclusion is that UUIDv7 IDs are roughly ordered, which is still useful for index locality, and that uniqueness and collision resistance are the only properties reliable across implementations.
The post does not cover bit-level guessability, referring to a separate post, and it cites RFC sections only up to 6.2. Readers choosing a generator can run the same clock-rollback test on their own library. Other recent software coverage on the site, such as OpenAI's Decisions API and the Respan gateway, shows how often a headline property depends on the fine print.
Sources
More in Software
- 01Wild 0.11.0 Can Link Kernel Modules, and Says COMDAT Support Slowed ItThe Rust linker's Oct. 24 release widens linker-script support and caps threads at 32, but its notes publish no benchmark numbers.
- 02Rune 1.3.1 Brings 39 Changes and Windows Fixes From a NewcomerThe GPLv3 IDE's Oct. 23 release credits 16 first-time contributors, yet its published binaries still cover only macOS and Linux.
- 03HumanLayer Open-Sources Cloud Code as Its Homepage Says Not YetThe Apache 2.0 repository has 12.3k stars, but self-hosting still needs WorkOS, Slack and Linear keys and a compose file with default passwords.
- 04Cloudflare Open-Sources a 450-Line Audit Skill, Not the Harness It BecameThe MIT-licensed security-audit skill has 43.2k GitHub stars, while the 128-repository system built from it stays private and its numbers are Cloudflare's own.