Command Palette

Search for a command to run...

UUID Generator: v1, v4, v7 Explained (And Which to Actually Use)

UUID Generator: v1, v4, v7 Explained (And Which to Actually Use)

T
Toolz Team
|Jul 1, 2026|16 min read

The first time UUIDs really mattered to me, I was moving a WordPress-adjacent SaaS from a single MySQL box to a setup with a read replica and a plan to shard later. Auto-increment IDs had been fine for years β€” until two services started inserting into what would become the same logical table, and suddenly id = 42 meant two different rows. That's the moment auto-increment quietly stops working, and UUIDs are the usual answer.

A UUID is a 128-bit value you can generate on any machine, at any time, with no coordination, and still trust to be unique. That "no coordination" part is the whole point: a mobile app offline on a plane, three microservices, and a background worker can all mint IDs simultaneously and never collide. The math backing that confidence is genuinely absurd, and I'll show you just how absurd in a second.

The UUID Generator on toolz.dev creates single or bulk UUIDs in multiple versions instantly, right in your browser β€” handy when you're seeding a table or need a throwaway ID for a test. This guide covers what the versions actually mean, which one to pick in 2026, how to store them without destroying your database index, and the mistakes I made so you can skip them.

TL;DR: For new database primary keys in 2026, generate UUID v7 β€” it's time-ordered so it indexes well, and it doesn't leak hardware like v1. Use v4 when you want pure unpredictability. Store them as a native uuid type or BINARY(16), never VARCHAR(36). Make them in bulk with the UUID Generator, and pair it with the Timestamp Converter to read the time baked into a v7. All client-side, all free.


What Is a UUID, Exactly?

A UUID (Universally Unique Identifier) is a 128-bit number used to identify something without a central authority handing out IDs. Microsoft calls the same thing a GUID (Globally Unique Identifier); they're identical in every way that matters. The canonical text form is 36 characters β€” 32 hex digits split into five hyphenated groups of 8-4-4-4-12:

550e8400-e29b-41d4-a716-446655440000

Two of those hex positions aren't random data β€” they're metadata. The 13th hex digit encodes the version (which generation strategy made it), and the first digit of the fourth group encodes the variant (which layout standard it follows β€” 8, 9, a, or b for the standard UUIDs). So in the example above, the 4 in the third group tells you it's a v4.

How unique is "unique," really?

After the version and variant bits are reserved, a v4 UUID has 122 random bits. That's 2^122 possible values, or about 5.3 undecillion:

5,316,911,983,139,663,491,615,228,241,121,400,000

To make that concrete: if you generated a billion UUIDs every second, you'd need roughly 86 years before you hit even a 50% chance of a single collision anywhere. In practical engineering terms, v4 collisions do not happen, and you can design as if they never will.


What's the Difference Between UUID v1, v4, and v7?

The specification β€” originally RFC 4122, now updated by RFC 9562 (2024) β€” defines several versions. Three matter for day-to-day work.

UUID v1 β€” timestamp + MAC address

v1 stitches together a 100-nanosecond timestamp (counting from October 15, 1582, the date the Gregorian calendar started β€” one of my favorite pieces of spec trivia) with the network card's MAC address. It's naturally time-ordered and you can extract the creation time from it.

The problem is right there in the definition: it embeds the MAC address of the machine that made it. That leaks hardware identity and, combined with the timestamp, makes IDs somewhat predictable. Example: 6ba7b810-9dad-11d1-80b4-00c04fd430c8. I'd only use v1 for legacy compatibility now.

UUID v4 β€” random

v4 is 122 bits of randomness and nothing else. It's the version most people mean when they say "UUID," and it's dead simple: no timestamp, no hardware, no order. Example: f47ac10b-58cc-4372-a567-0e02b2c3d479.

The upside is that it leaks nothing and is unpredictable, which is exactly what you want for anything that shouldn't be guessable. The downside is that it's random, so consecutive inserts scatter all over your index β€” which, as I found out, has a real performance cost at scale.

UUID v7 β€” time-ordered + random

v7 is the modern compromise, standardized in RFC 9562. The first 48 bits are a Unix timestamp in milliseconds; the rest is random. Example: 018e4880-d4d0-7b9c-8c37-2a5c0f1e3d8a.

That layout means v7 IDs sort chronologically β€” new rows land at the "end" of a B-tree index instead of scattering β€” while still being globally unique and coordination-free. It leaks approximate creation time (usually fine) but not hardware. For new projects, this is my default primary key, and it's the direction the IETF now points too.

Here's the tradeoff at a glance:

Version Ordered? Leaks Best for
v1 Yes (time) MAC address + time Legacy systems only
v4 No (random) Nothing Unguessable tokens, general IDs
v7 Yes (time) Approximate creation time New database primary keys

The lesser-used versions exist too: v3 and v5 are deterministic hashes of a namespace plus a name (v5 uses SHA-1 and is preferred over v3's MD5), v6 is a reordered v1, and v8 is reserved for custom implementations.


Should You Use UUIDs or Auto-Increment IDs?

This is the debate I've had in more design reviews than any other, so here's the framework I actually use rather than a religious answer.

Stick with auto-increment when you have a single database, performance and storage are tight, and humans need to read the IDs. An integer is 4–8 bytes versus a UUID's 16, integer comparisons are faster, and "order #12345" is a lot easier to read down the phone than a 36-character UUID. On a single box with no sharding, auto-increment is genuinely the simpler, faster choice β€” don't reach for UUIDs out of fashion.

Switch to UUIDs when any of these are true: you're distributed (multiple services or servers minting IDs independently), you're worried about enumeration (auto-increment IDs are guessable and quietly reveal your record counts β€” /users/1234 tells an attacker you have fewer than 1,235 users), you need to merge data from multiple databases without collisions, or you want clients to generate IDs before they sync. That enumeration point is a real security consideration people underrate.

And the v7 middle ground: UUID v7 gives you the distributed generation of a UUID and the index-friendly ordering of auto-increment, without leaking record counts. For most new projects in 2026 that need non-sequential IDs, v7 is the answer that ends the debate.


How Do You Store UUIDs Without Wrecking Your Index?

This is the section born from my own expensive mistake, so pay attention here if nowhere else.

On that migration I mentioned, I stored the new UUIDs as VARCHAR(36) because it was the obvious, readable thing to do. It worked β€” and then the table grew, and inserts and joins got measurably slower. Two problems compounded: I was spending 36 bytes per ID instead of 16, and I was using random v4 UUIDs, so every insert landed at a random spot in the primary-key index, fragmenting it and thrashing the buffer pool. The fix was storing them as binary and, on the next project, switching to v7 so inserts stayed sequential.

PostgreSQL has a native uuid type β€” use it. It stores 16 bytes and compares fast:

CREATE EXTENSION IF NOT EXISTS "pgcrypto";

CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);

MySQL has no native UUID type, so store BINARY(16) and convert with UUID_TO_BIN() / BIN_TO_UUID(). The second argument matters:

CREATE TABLE users (
    id BINARY(16) PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- The `true` swaps the timestamp bytes for better index locality on v1
INSERT INTO users (id, name, email)
VALUES (UUID_TO_BIN(UUID(), true), 'Alice', '[email protected]');

SELECT BIN_TO_UUID(id, true) AS id, name, email FROM users;

The rule to remember: native uuid type where you have one, BINARY(16) where you don't, and VARCHAR(36) basically never for a key you'll index and join on.


How Do You Generate UUIDs in Code?

For a quick one-off, the UUID Generator is faster than opening a REPL. In code, every major language has this built in or a step away.

JavaScript / TypeScript β€” the browser and Node both ship a v4 generator now:

const id = crypto.randomUUID();   // v4, no dependency needed
// For v7, use the 'uuid' package:
import { v7 as uuidv7 } from 'uuid';
const ordered = uuidv7();

Python:

import uuid
uuid.uuid4()                                  # random
uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com') # deterministic (SHA-1)

Java: UUID.randomUUID() gives you v4 out of the box; v7 needs a library like java-uuid-generator or a small RFC 9562 implementation.

Go: github.com/google/uuid gives you both β€” uuid.New() for v4 and uuid.NewV7() for v7.

Note that native runtime helpers almost always give you v4. If you specifically want v7 for its ordering, you usually need a library, since it's the newer standard and not every stdlib has caught up.


Where Do UUIDs Actually Show Up in Real Systems?

It's easy to talk about UUIDs in the abstract, so here are the concrete places I've relied on them, because the version you pick really does depend on the job.

Database primary keys in a distributed setup. This is the classic case and the one that started this article for me. The moment more than one writer can insert into the same logical table β€” replicas, shards, or two services sharing a schema β€” auto-increment breaks. A v7 primary key solves the coordination problem and still indexes cleanly because it's time-ordered.

Client-generated IDs for offline-first apps. A mobile app or a browser SPA often needs to create a record before it can talk to the server β€” think a note written on a plane, or an optimistic UI that shows the new row instantly. If the client mints a UUID up front, the record has a stable identity from the first keystroke and syncs later without a server round-trip to "get an ID." I've used this to make forms feel instant even on flaky connections.

Non-enumerable resource identifiers in URLs and APIs. Putting /orders/1042 in a URL quietly tells anyone that you've had at most 1,042 orders, and lets them walk /orders/1041, /orders/1040, and so on. Swapping in a UUID removes both the business-metric leak and the easy enumeration. For anything a user can see in a URL, this is worth doing β€” though remember a UUID is not an access-control mechanism; you still need real authorization checks behind it.

Correlation IDs for tracing. When a single request fans out across five microservices, attaching one UUID as a correlation ID and logging it at every hop turns "somewhere in this mess something failed" into a single greppable string across all your logs. This is one place where even a plain v4 is perfect β€” you don't need ordering, just uniqueness.

Idempotency keys. Payment and webhook APIs often ask the client to send a UUID as an idempotency key so that a retried request doesn't charge a card twice. The client generates it once, reuses it on retries, and the server dedupes on it. It's a small pattern that prevents a very expensive class of bug.


Frequently Asked Questions

What is a UUID used for?

A UUID uniquely identifies something β€” a database row, an API resource, a session, an uploaded file, a trace across microservices β€” without needing a central service to hand out IDs. It's the go-to whenever multiple systems or clients must create identifiers independently and still be sure they won't clash. You can generate one instantly with the UUID Generator on toolz.dev.

Can two UUIDs ever be identical?

In theory yes; in practice no. A v4 UUID has 122 random bits, giving about 5.3 undecillion possibilities. You'd need to generate on the order of 2.7 quintillion UUIDs before reaching a 50% chance of even one collision. For every real engineering purpose, you can treat UUIDs as guaranteed unique.

Which UUID version should I use in 2026?

For new database primary keys, UUID v7 β€” it's time-ordered for efficient indexing while staying globally unique, and it's the current IETF recommendation under RFC 9562. Use v4 when unpredictability matters, such as identifiers that must not be guessable. Avoid v1 for new work because it embeds the generating machine's MAC address.

Are UUIDs sequential?

v1 and v7 are time-ordered, so IDs generated later sort after earlier ones; v4 is fully random with no order. Sequential ordering is what makes v7 friendly to B-tree indexes β€” new rows append rather than scatter. If you're using random v4 as a primary key on a large table, that lack of order can hurt insert and index performance.

How should I store UUIDs in a database?

Use the native uuid type if your database has one (PostgreSQL does). Otherwise store BINARY(16), and in MySQL 8.0+ convert with UUID_TO_BIN() and BIN_TO_UUID(). Avoid VARCHAR(36) or CHAR(36) for keys β€” string storage wastes 20 bytes per row and slows every comparison, which adds up fast on big tables.

What's the difference between a UUID and a GUID?

They're the same thing. UUID is the term from RFC 4122 used across most languages and platforms; GUID is Microsoft's name for it, common in Windows and .NET. The format and guarantees are identical, so you can treat a GUID and a UUID interchangeably.

Can I extract the creation time from a UUID?

From v1, v6, and v7, yes β€” they encode a timestamp. v7 stores a millisecond Unix timestamp in its first 48 bits, which you can decode and read with the Timestamp Converter. v4 and v5 contain no time information, so there's nothing to extract from them.

Is UUID v4 secure enough for session tokens?

Not on its own. v4's 122 random bits are unpredictable, but session and authentication tokens generally want at least 256 bits from a cryptographically secure generator. Use a purpose-built secure random token for auth, and reserve UUIDs for identifying resources rather than protecting them.

How do I generate a UUID?

Use your language's built-in generator: crypto.randomUUID() in modern browsers and Node.js, uuid.uuid4() in Python, or Guid.NewGuid() in .NET each produce a v4 UUID in a single call. For a quick one-off or a batch, generate them instantly with the UUID Generator on toolz.dev β€” no code required.

How many characters is a UUID?

A UUID is 36 characters in its canonical text form: 32 hexadecimal digits plus the four hyphens that split it into 8-4-4-4-12 groups. That text encodes 128 bits, which is why storing it as 16 raw bytes with BINARY(16) is far more compact than the 36-character string.


Wrapping Up

UUIDs are one of those foundations you don't think about until a system grows past a single database β€” and then they're everything. The 2026 short version: default to v7 for new primary keys, use v4 when you need unguessable IDs, store them as native uuid or BINARY(16), and skip v1 for anything new. Learn from my VARCHAR(36) afternoon so you don't repeat it.

Generate them instantly with the free UUID Generator on toolz.dev β€” single or bulk, any version, all client-side with nothing uploaded. When you need to read the time inside a v7, reach for the Timestamp Converter, and browse the rest of the coding tools β€” 600+ free utilities β€” over at toolz.dev.

Comments

0 comments

0/2000 characters

No comments yet. Be the first to share your thoughts!