UUID v4 vs v7: which should your database use?
UUID v4 and UUID v7 solve the same basic problem — generating a unique identifier without coordinating with a central authority — but they take fundamentally different approaches, and that difference has real, measurable consequences for database performance at scale.
UUID v4 is fully random. Every one of its 122 usable bits comes from a random number generator, which is exactly what makes collisions astronomically unlikely even across billions of IDs generated independently on different machines. It's a genuinely good design for unpredictability — you cannot guess the next ID from a previous one, which matters when IDs are exposed publicly and shouldn't reveal information like creation order or approximate record count.
That same randomness is what makes v4 problematic as a primary key in a B-tree-indexed database. Most relational databases store rows physically ordered (or heavily influenced) by the primary key's index structure. When new IDs arrive in a random order, each insert lands in a random location within the index rather than appending to the end — this causes constant page splits, fragments the index over time, and degrades both insert performance and range-query performance as the table grows. This isn't a theoretical concern; it's a well-documented, measurable effect on databases like PostgreSQL and MySQL at meaningful scale.
UUID v7 was designed specifically to address this. It embeds a millisecond-precision timestamp in the leading bits of the UUID, with the remaining bits filled with randomness for uniqueness within that millisecond. The practical effect: UUIDs generated close together in time sort close together in value. Inserts into an index become mostly sequential again — new rows land near the end of the index rather than scattered randomly throughout it — which restores much of the insert performance and index locality that auto-incrementing integers have always had, while keeping the distributed-generation benefits that made UUIDs attractive in the first place.
The trade-off is exactly the flip side of v4's strength: v7 UUIDs are not fully unpredictable. Because they encode a timestamp, someone with a v7 UUID can extract an approximate creation time from it, and consecutive UUIDs generated in the same system reveal their relative ordering. For most internal database primary keys, this isn't a meaningful problem — but if you're using UUIDs specifically because unpredictability is a security property you need (a password reset token, for instance, where guessability matters), v4's full randomness is still the right tool, not v7.
This makes the decision fairly clean in practice: for internal database primary keys, where you want the distributed-generation benefits of UUIDs without paying the index-fragmentation cost, v7 is generally the better default going forward. For tokens or identifiers where unpredictability itself is the security property you're relying on, stick with v4 or an equivalent cryptographically random generator.
It's worth noting that v7 support varies by database and driver — some databases can generate v7 natively, others need it generated in application code before insertion. Check what your specific stack supports before assuming it's a drop-in replacement for however you're currently generating v4 UUIDs.
If you need to quickly generate UUIDs for testing, or want to inspect the structure of an existing one, our UUID Generator produces cryptographically random v4 UUIDs in bulk, right in your browser, with formatting options to match whatever your system expects.
Found this helpful?
SyncTonight's tools and guides are free and always will be. If this post saved you some debugging time, a coffee goes a long way — no pressure, just appreciated.
☕ Buy me a coffee