Identifiers

UUID and GUID Explained: Versions 1, 4, 5 and 7, Formats and Collisions

What UUIDs and GUIDs are, how v1, v3, v4, v5 and v7 differ, why UUID v7 is now preferred for database keys, format options, collision odds, and when to use them.

HandyUtils January 2, 2026 13 min read

A UUID (Universally Unique Identifier) is a 128-bit number, written as 32 hexadecimal digits in five hyphenated groups, that is designed to be unique across every computer in the world without any central authority handing them out. A typical one looks like 550e8400-e29b-41d4-a716-446655440000. Because any machine can generate one at any time with no coordination and no realistic chance of a duplicate, UUIDs are the standard choice for database keys, API resource IDs, session identifiers and correlation IDs in distributed systems. GUID (Globally Unique Identifier) is Microsoft's name for exactly the same thing.

UUID format and structure

The canonical text form is 8-4-4-4-12 hexadecimal digits, 36 characters including the four hyphens:

xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
  • M is the version nibble. It tells you how the UUID was generated: 1, 3, 4, 5, 7 and so on.
  • N is the variant. For every UUID described here it is 8, 9, a or b, which marks the layout defined by RFC 4122 and its successor RFC 9562.

So in f47ac10b-58cc-4372-a567-0e02b2c3d479 the 4 at the start of the third group says "version 4" and the a at the start of the fourth group is the variant. Two special values are also defined: the nil UUID 00000000-0000-0000-0000-000000000000 and, since RFC 9562, the max UUID ffffffff-ffff-ffff-ffff-ffffffffffff.

UUID versions at a glance

Version Built from Sortable by time Deterministic Typical use
v1 60-bit timestamp + clock sequence + 48-bit node ID (historically the MAC address) Partly (timestamp bits are in the wrong order for string sorting) No Legacy systems; MySQL's UUID() function
v3 MD5 hash of a namespace UUID and a name No Yes Stable IDs derived from names, where v5 is unavailable
v4 122 random bits No No General purpose; the most common version
v5 SHA-1 hash of a namespace UUID and a name No Yes Stable IDs derived from names (URLs, DNS names, OIDs)
v7 48-bit Unix millisecond timestamp + 74 random bits Yes No Database primary keys and anything that benefits from time ordering

Versions 2 (DCE security), 6 (a v1 with the timestamp fields reordered so it sorts correctly) and 8 (a free-form layout for custom schemes) also exist but are rarely used directly.

Version 1: time-based

A v1 UUID packs a 60-bit timestamp (100-nanosecond intervals since 15 October 1582), a 14-bit clock sequence to handle clock resets, and a 48-bit node identifier that was originally the machine's MAC address. The timestamp makes v1 IDs unique on a single machine even when generated rapidly, but the fields are stored low-order first, so sorting the strings does not sort by time, and the MAC address leaks which machine created the record. Modern implementations usually substitute random bits for the node ID.

Versions 3 and 5: name-based

These hash a namespace UUID together with a name, so the same input always produces the same UUID. RFC 9562 predefines namespaces for DNS names (6ba7b810-9dad-11d1-80b4-00c04fd430c8), URLs, ISO OIDs and X.500 names. v3 uses MD5 and v5 uses SHA-1; neither hash needs to be cryptographically strong for this purpose, but v5 is the recommended choice.

const { v5: uuidv5 } = require('uuid');
uuidv5('example.com', uuidv5.DNS);   // always cfbff0d1-9375-5685-968c-48ce8b15ae17

Version 4: random

A v4 UUID sets the version and variant bits and fills the remaining 122 bits with random data from a cryptographically secure generator. It is the simplest to implement, reveals nothing about when or where it was made, and is what crypto.randomUUID() in browsers and Node.js, uuid.uuid4() in Python and Guid.NewGuid() in .NET all produce.

crypto.randomUUID();   // e.g. "f47ac10b-58cc-4372-a567-0e02b2c3d479"

UUID v7

UUID v7 was standardised in RFC 9562 (May 2024) to solve the one real weakness of v4 as a database key: random keys scatter inserts across the whole index. A v7 UUID puts the current time in the most significant bits, so new IDs are always larger than older ones and sort in creation order, while the remaining bits stay random so the ID is still unguessable.

Layout

+---------------------------------------------------------------+
|                     unix_ts_ms (48 bits)                      |  Unix time in milliseconds
+------+------------------+----+---------------------------------+
| ver  |  rand_a (12)     |var |        rand_b (62 bits)         |  ver = 0111 (7), var = 10
+------+------------------+----+---------------------------------+
  • 48 bits of Unix timestamp in milliseconds, which is enough until the year 10889.
  • 4 bits of version (7).
  • 12 bits rand_a, random, or optionally a sub-millisecond counter so IDs made in the same millisecond still sort in order.
  • 2 bits of variant.
  • 62 bits rand_b, random.

The example from the RFC, 017f22e2-79b0-7cc3-98c4-dc0c0c07398f, encodes the timestamp 017f22e279b0 (22 February 2022, 19:22:22 UTC) followed by the version 7, then random bits.

Why v7 is now preferred for database keys

  • Index locality. B-tree indexes in PostgreSQL, MySQL, SQL Server and SQLite append new v7 keys at the right-hand end of the index instead of splitting pages at random positions, which means less write amplification, smaller indexes and better cache behaviour. This is the same reason auto-increment integers perform well.
  • Natural ordering. ORDER BY id gives creation order, and range queries by time become possible without a separate indexed timestamp column.
  • Still safe to generate anywhere. Clients, microservices and offline apps can mint v7 IDs without coordination, exactly as with v4.
  • Still unguessable. 74 random bits per ID remain, so an attacker who knows one ID cannot predict the next.

The trade-off is that a v7 UUID reveals roughly when the record was created, which is usually harmless but matters if creation time is itself sensitive.

Generating v7 UUIDs

Support arrived across the ecosystem in 2024 and 2025:

Platform How
.NET 9+ Guid.CreateVersion7()
Python 3.14+ uuid.uuid7() (earlier versions: the uuid6 or uuid7 packages)
PostgreSQL 18+ uuidv7() built in (earlier versions: the pg_uuidv7 extension)
Node.js / JavaScript import { v7 } from 'uuid' (uuid 10+)
Go uuid.NewV7() from github.com/google/uuid
Java No JDK method yet; use a library such as uuid-creator
MariaDB 11.7+ UUID_v7()

Our UUID Generator generates v1, v4, v5 and v7 UUIDs in the browser, in bulk, with your choice of case and formatting.

UUID vs GUID

They are the same thing. GUID is the name Microsoft adopted for the identifier when it built COM in the 1990s, and it persists throughout Windows, .NET (System.Guid), SQL Server (the uniqueidentifier type) and Microsoft documentation. Everyone else says UUID. The 128-bit value, the version and variant bits, and the hyphenated text form are identical, and a GUID produced by Guid.NewGuid() is a perfectly ordinary version 4 UUID.

Two habits distinguish Microsoft's usage. First, the Windows registry, COM class IDs and older Microsoft tooling wrap the value in braces: {550e8400-e29b-41d4-a716-446655440000}. Second, Microsoft code often writes GUIDs in uppercase. Neither changes the value. .NET's Guid.ToString() accepts a format string for the common variants: "N" for 32 digits with no hyphens, "D" for the default hyphenated form, "B" for braces and "P" for parentheses. Our GUID Generator produces the braced, uppercase style directly.

One historical wrinkle: SQL Server sorts uniqueidentifier values by the last six bytes first, not left to right, which is why NEWSEQUENTIALID() puts its incrementing bytes at the end and why a v7 UUID stored in SQL Server does not sort in time order without special handling.

Formatting options

All of these represent the same 128-bit value:

Standard:   550e8400-e29b-41d4-a716-446655440000
Uppercase:  550E8400-E29B-41D4-A716-446655440000
Braces:     {550e8400-e29b-41d4-a716-446655440000}
No hyphens: 550e8400e29b41d4a716446655440000
URN:        urn:uuid:550e8400-e29b-41d4-a716-446655440000

RFC 9562 says generators should output lowercase and parsers should accept either case.

Collision probability

A v4 UUID has 122 random bits, so there are about 5.3 × 1036 possible values. By the birthday-problem maths, you would need to generate roughly 2.7 × 1018 UUIDs, about one billion per second for around 85 years, before the chance of a single duplicate reached 50 percent. To get the risk of one duplicate down to one in a billion you can still generate about 103 trillion of them.

For every practical purpose, v4 and v7 collisions do not happen, provided the random bits come from a proper cryptographic generator. The realistic causes of duplicate UUIDs are bugs: a seeded pseudo-random generator, a copied virtual machine image with a cached v1 node ID, or code that reuses an ID by mistake.

UUIDs vs auto-increment IDs

Feature UUID Auto-increment integer
Size 16 bytes (36 characters as text) 4 or 8 bytes
Generated by Any client or server, offline The database, at insert time
Guessable No (v4, v7) Yes: /users/1042 implies /users/1043 exists
Reveals record count No Yes
Merging databases No conflicts Conflicts
Index insert pattern Random (v4) or sequential (v7) Sequential

Use UUIDs when records are created in more than one place, when IDs are exposed in URLs or APIs, when data from separate systems may later be merged, or when clients need to create records before they reach the server. Use integers for small, single-database applications where simplicity and the shortest possible keys matter more.

UUIDs in databases

Store UUIDs as 16-byte binary values, not 36-character strings: PostgreSQL has a native uuid type, SQL Server has uniqueidentifier, and MySQL and SQLite can use BINARY(16) or BLOB. A string column more than doubles the storage and slows every index comparison.

-- PostgreSQL 18+
CREATE TABLE orders (
    id UUID PRIMARY KEY DEFAULT uuidv7(),
    customer_id UUID NOT NULL,
    created_at TIMESTAMPTZ DEFAULT now()
);

-- PostgreSQL 13 to 17 (random v4)
CREATE TABLE orders (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    ...
);

If you are on a database without native v7 support, generate the ID in the application (Guid.CreateVersion7(), uuid.uuid7(), v7()) and pass it in the insert. The performance difference between random and time-ordered keys grows with table size, so choose v7 for tables that will be large or write-heavy.

When to use UUIDs

Good fits: primary keys in distributed or multi-tenant systems, public identifiers in URLs and APIs, idempotency keys, correlation IDs in logs and traces, file names that must not be guessable, and records created offline.

Poor fits: tiny lookup tables where an integer is clearer, human-facing references such as order numbers or URL slugs, and security tokens. A v4 UUID is unpredictable, but a session token should be generated and handled as a secret in its own right rather than borrowed from an ID scheme.

Frequently Asked Questions

What is the difference between UUID and GUID?

There is no technical difference. GUID (Globally Unique Identifier) is Microsoft's name for the 128-bit identifier that everyone else calls a UUID (Universally Unique Identifier). They share the same layout, the same version and variant bits and the same text format. The only visible differences are conventions: Microsoft tooling often shows GUIDs in uppercase and wraps them in braces, as in {550E8400-E29B-41D4-A716-446655440000}.

Which UUID version should I use?

Use v7 for database primary keys and any ID where sorting by creation time is useful, because its time-ordered layout keeps indexes compact. Use v4 when you want a purely random ID that reveals nothing about when it was made, which is the right default for most other purposes. Use v5 when the same input must always produce the same ID, such as deriving an identifier from a URL or a name. Avoid v1 in new systems unless a legacy component requires it, and avoid v3 in favour of v5.

Can two UUIDs be the same?

In theory yes, in practice no. A v4 UUID has 122 random bits, so you would need to generate billions of IDs every second for decades before a duplicate became likely. When duplicates do occur it is almost always because of a bug rather than bad luck: a random number generator seeded with the same value on two machines, a cloned virtual machine reusing a v1 node identifier, or application code that copies an existing ID. Use your platform's cryptographic random source and the risk is negligible.

What is UUID v7?

UUID v7 is a version defined in RFC 9562 that starts with a 48-bit Unix timestamp in milliseconds, followed by the version bits and 74 random bits. Because the timestamp comes first, v7 IDs sort in the order they were created, which makes them much friendlier to database indexes than random v4 IDs while remaining unguessable and safe to generate on any machine without coordination. It is now the recommended choice for new primary keys.

Are UUIDs secure enough to use as tokens?

A v4 or v7 UUID from a cryptographic random source is unguessable, so it is fine as a public identifier that must not be enumerable, such as a resource ID in a URL. It is not designed as a security credential: v1 and v7 embed a timestamp, some libraries fall back to weaker random sources, and the 122 random bits of a v4 are fewer than a dedicated 256-bit token would carry. For session tokens, password-reset links and API keys, generate a purpose-built random secret and store a hash of it.

How do I generate a UUID?

Every mainstream platform has a built-in generator: crypto.randomUUID() in browsers and Node.js, uuid.uuid4() or uuid.uuid7() in Python, Guid.NewGuid() or Guid.CreateVersion7() in .NET, java.util.UUID.randomUUID() in Java, gen_random_uuid() or uuidv7() in PostgreSQL and uuidgen on the command line. For one-off or bulk IDs without writing code, the UUID Generator produces v1, v4, v5 and v7 UUIDs in any format.

Summary

  • A UUID is a 128-bit identifier written as 36 hexadecimal characters; a GUID is the same thing under Microsoft's name.
  • The version nibble tells you how it was made: v1 from time and node, v3 and v5 from a hashed name, v4 from random bits, v7 from a millisecond timestamp plus random bits.
  • Choose v7 for database keys, v4 for general-purpose random IDs, and v5 when the ID must be reproducible from a name.
  • Collisions are a theoretical curiosity; real duplicates come from bugs in random number generation.
  • Store UUIDs as 16-byte binary or native uuid columns, not as strings.

Need some now? Generate v1, v4, v5 or v7 UUIDs with our UUID Generator, braced Microsoft-style values with the GUID Generator, or plain random values with the Random Number Generator.

Related Topics
uuid guid uuid v7 uuid v4 uuid vs guid unique identifier uuid versions uuid format random id database primary key rfc 9562
Share this article