dev

UUID v1 vs v4: Which One Should You Actually Use?

UUID v1 and v4 solve the same problem — a unique ID — in completely different ways, and picking the wrong one leaks information or hurts database performance. Here's what's actually inside a UUID, why v1 embeds your MAC address, why v4 can slow down a database index, and how to pick correctly.

👤FileConvy Team📅 July 28, 2026⏱️ 6 min read
#uuid#uuid generator#unique id#database primary key#developer tools

f47ac10b-58cc-4372-a567-0e02b2c3d479 and 1ee89e58-1dd2-11b2-8080-808080808080 are both valid UUIDs, both 128 bits, both formatted the same way — and both were built by completely different methods that leak different information and behave differently once they hit a database. Most people generate a UUID, pick whatever version their library defaults to, and move on. That's fine most of the time, but the two most common versions — v1 and v4 — trade off privacy, sortability, and database performance in ways that matter once you're past a prototype.

What's Actually Inside a UUID

A UUID is a 128-bit number, almost always written as 32 hex digits split into five groups: 8-4-4-4-12. Two of those bits positions are reserved to encode metadata: a version nibble (which algorithm built it) and a variant (which spec it follows — nearly always the RFC one). Everything else is payload, and what goes into that payload is exactly what separates the versions.

  • v1 — payload is a 60-bit timestamp (100-nanosecond intervals since Oct 15, 1582, for historical reasons) plus a 48-bit "node ID," which is supposed to be the generating machine's MAC address.
  • v4 — payload is 122 random bits, full stop. No timestamp, no machine identity, nothing derived from anything.

Same shape, same length, opposite philosophy: v1 is deterministic and traceable, v4 is pure noise.

UUID v1: Time-Based, and It Knows Where It Came From

A v1 UUID is built from the current timestamp and the machine's network hardware address. That has one genuine upside — the timestamp component means v1 UUIDs generated in sequence are roughly time-ordered, which you don't get for free with v4.

The downside is the reason v1 fell out of favor for anything public-facing: it embeds the generating machine's MAC address in the ID itself. Anyone who has a v1 UUID can extract the exact millisecond it was created and the network hardware identifier of the machine that made it. That's a real privacy leak if the UUID ever ends up in a URL, an API response, or a support ticket a customer can see — it's effectively broadcasting internal infrastructure details. Most v1 implementations today substitute a random 48 bits for the node ID instead of the real MAC specifically to avoid this, but that's a workaround bolted onto the spec, not what v1 was designed to do.

UUID v4: Private, But Not Free Either

v4 has no timestamp and no machine identity — it's 122 bits of randomness, which is why it's the default in almost every UUID library today. The tradeoff shows up somewhere else: database performance.

Primary keys and indexes are typically stored as B-trees, which perform best when new values are inserted in roughly ascending order — new rows land at the end of the tree, and recently-inserted rows (the ones you're most likely to query next) stay clustered together in cache. A random v4 UUID inserted as a primary key lands at a random point in the index every single time, which fragments the B-tree, forces more disk pages into memory, and measurably slows down inserts and range queries as a table grows. This is a well-documented issue in Postgres and MySQL alike — it's not theoretical, it's why time-ordered ID schemes (and eventually UUID v7, standardized in 2024 specifically to fix this) exist at all.

So Which One Should You Use?

UUID v1UUID v4
PayloadTimestamp + machine IDPure random
Roughly sortable by creation timeYesNo
Leaks machine/network infoYes (unless node ID is randomized)No
Database index-friendlyYesNo — fragments B-tree indexes
Good for public-facing IDs (URLs, API responses)NoYes
Good default when you're not sureNoYes

Default to v4 for anything a user or client can see — order IDs, API resource IDs, file IDs, session-adjacent identifiers. It leaks nothing about your infrastructure and the collision odds are close enough to zero to ignore (you'd need to generate roughly 2.7 quintillion v4 UUIDs before hitting a 50% chance of a single collision).

Only reach for v1 in closed, internal systems where you specifically want the built-in time ordering and you've confirmed the node ID isn't a real MAC address (check your library's docs — many randomize it by default now, some don't). If you need time-ordering and public-safety, that's specifically the gap UUID v7 was created to fill — worth knowing about even if it's not yet as universally supported as v1/v4.

Two Pitfalls Worth Knowing

"UUIDs are guaranteed unique." Not literally — the collision probability is astronomically low, not zero. For any system where an actual collision would be catastrophic (rare), that distinction matters; for everything else, it's a non-issue.

"I can sort UUIDs as strings to get chronological order." Only true for v1, and only if you reorder the bytes correctly — the timestamp isn't stored in the same order it's displayed in, so naively sorting v1 UUIDs as text does not give you chronological order. v4 gives you no ordering information at all, by design.

Generating Either One

UUID Generator generates both v1 and v4 UUIDs on demand, in bulk, free — pick the version, pick a count, and copy the results. Useful for seeding test data, generating IDs during development, or just checking what a given version actually looks like before wiring it into your schema.

Quick FAQ

Can two UUIDs actually collide? Mathematically yes, practically no — for v4 specifically, you'd need quintillions of UUIDs generated before collision odds become non-negligible. It's not worth designing around for typical applications.

Is UUID v4 safe to use as a security token (session ID, password reset link)? Only if your language's UUID library uses a cryptographically secure random number generator (CSPRNG) — most modern ones do, but it's implementation-dependent, not guaranteed by the v4 spec itself. If you're generating a security-sensitive token, use your language's dedicated secure-token function rather than assuming any UUID v4 generator is safe for that purpose.

Should I use a UUID or an auto-incrementing integer for a database primary key? Auto-increment integers are faster to index and smaller to store, but don't work well across distributed systems where multiple services generate IDs independently — UUIDs solve that at the cost of index performance (see above). Many teams split the difference: an internal auto-increment integer plus a public-facing UUID.

Why does my UUID library default to v4 instead of v1? Because v4 is safe to expose publicly with no privacy leak and no configuration to get wrong, which makes it the safer default even though it costs you sortability.

Related Free Tools

SHARE THIS ARTICLE

TwitterLinkedIn
← Back to Blog

Related Articles

dev
Unix Timestamps Explained: Why Your Dates Are Off By an Hour (or a Day)
6 min read
dev
Cron Expressions Explained: How to Write One Without Guessing
5 min read
dev
Why Is My JSON Invalid? Common JSON Errors Explained (and How to Fix Them)
5 min read

Try FileConvy Free Tools

100+ tools — PDF, Image, Text, Dev & Calculators. No signup required.

Explore All Tools →