UUID Generator Guide: All Versions Explained
· Cosyslabs
A UUID (Universally Unique Identifier) is a 128-bit identifier that can be generated by any system without central coordination while maintaining practical uniqueness. UUIDs are standardized in RFC 9562 (2024) and represented as 32 hex digits in five groups: xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx. The version digit M and variant bits N identify the generation algorithm.
UUID Versions Overview
| Version | Source of Uniqueness | Sortable | Recommended |
|---|---|---|---|
| v1 | Timestamp + MAC address | Partially | No (deprecated) |
| v2 | DCE Security (POSIX UID) | No | No (obsolete) |
| v3 | MD5 hash of namespace + name | Yes (deterministic) | No (use v5) |
| v4 | Random | No | Yes (when unpredictability needed) |
| v5 | SHA-1 hash of namespace + name | Yes (deterministic) | Yes |
| v6 | Reordered v1 timestamp | Yes | No (use v7) |
| v7 | Unix ms timestamp + random | Yes | Yes (DB primary keys) |
| v8 | Custom (implementation-defined) | — | Context-specific |
UUID v4: Random
UUID v4 uses 122 bits of cryptographically random data (6 bits are fixed for version and variant):
f47ac10b-58cc-4372-a567-0e02b2c3d479
^ ^
4 [89ab] — version and variant markers
// Modern browsers and Node.js 14.17+
const id = crypto.randomUUID();
// Python
import uuid
id = str(uuid.uuid4())
// Go
import "github.com/google/uuid"
id := uuid.New().String()
// Rust
use uuid::Uuid;
let id = Uuid::new_v4().to_string();
Use UUID v4 when:
- Generating tokens, session IDs, API keys, or invite codes
- Security requires IDs to be unpredictable
- Creation time must not be inferable from the ID
- IDs are exposed to users or in URLs
UUID v7: Time-Ordered (Recommended for Databases)
UUID v7 (RFC 9562, 2024) embeds a 48-bit Unix millisecond timestamp in the most significant bits, making IDs sortable by generation time:
01905b80-3e40-7abc-8def-123456789abc
^^^^^^^^ ^^^^
48-bit Unix ms timestamp
import { v7 as uuidv7 } from "uuid";
const id = uuidv7();
// Node.js 21+ native support (via --experimental-uuid-v7)
// PostgreSQL 17+ native uuidv7() function
import uuid
# Python stdlib does not yet include v7 — use uuid6 package
from uuid6 import uuid7
id = str(uuid7())
-- PostgreSQL 17+
SELECT uuidv7();
-- PostgreSQL 14-16
CREATE EXTENSION IF NOT EXISTS "pg_uuidv7";
SELECT uuid_generate_v7();
-- MySQL 8.0 (manual construction)
SELECT LOWER(
CONCAT(
LPAD(HEX(FLOOR(UNIX_TIMESTAMP(NOW(3)) * 1000)), 12, '0'),
'-7',
LPAD(HEX(FLOOR(RAND() * POW(2, 12))), 3, '0'),
'-',
LPAD(HEX(FLOOR(RAND() * POW(2, 14)) + 32768), 4, '0'),
'-',
LPAD(HEX(FLOOR(RAND() * POW(2, 48))), 12, '0')
)
);
UUID v7 advantages for databases:
- Sequential inserts avoid B-tree fragmentation
ORDER BY idgives chronological order- Index cache hit rate improves significantly
- Partitioning by time works naturally
UUID v7 limitations:
- Embeds creation timestamp — avoid for security-sensitive IDs
- Requires monotonic clock; two UUIDs in the same millisecond need sub-ms counter
UUID v5: Name-Based (Deterministic)
UUID v5 generates the same UUID for the same namespace + name combination using SHA-1. This is useful for content-addressable systems:
import { v5 as uuidv5 } from "uuid";
// Standard namespaces (RFC 4122)
const DNS_NAMESPACE = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
const URL_NAMESPACE = "6ba7b811-9dad-11d1-80b4-00c04fd430c8";
// Always produces the same UUID for the same input
const id = uuidv5("example.com", DNS_NAMESPACE);
// "cfbff0d1-9375-5685-968c-48ce8b15ae17" — always this value
const pageId = uuidv5("https://example.com/page", URL_NAMESPACE);
import uuid
ns = uuid.NAMESPACE_URL
id = uuid.uuid5(ns, "https://example.com/page")
UUID v5 use cases:
- Converting existing string identifiers to UUIDs deterministically
- Content-addressed storage (same content → same ID)
- Generating stable IDs from user emails or domain names for migration
- Creating test fixtures with reproducible IDs
Note: UUID v3 uses MD5 instead of SHA-1. Prefer v5 for new projects since SHA-1 is deprecated (though for UUID purposes, the security weakness of MD5/SHA-1 is less critical than their use for cryptographic signatures).
Database Storage Strategies
PostgreSQL
Use the native uuid type — it stores as 16 bytes (not 36-char string):
CREATE TABLE users (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
-- For UUID v7 (PostgreSQL 17+):
-- id uuid DEFAULT uuidv7() PRIMARY KEY,
name text NOT NULL,
created_at timestamptz DEFAULT now()
);
MySQL
Avoid VARCHAR(36) for UUIDs. Use BINARY(16):
CREATE TABLE users (
id BINARY(16) NOT NULL DEFAULT (UUID_TO_BIN(UUID(), 1)),
name VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
-- Query
SELECT BIN_TO_UUID(id) as id, name FROM users;
The second argument 1 to UUID_TO_BIN reorders the bytes to make v1 UUIDs sortable. For UUID v7, this reordering is not needed.
MongoDB
MongoDB's ObjectId is a 12-byte time-ordered identifier similar to UUID v7. When you need proper UUID v7 with MongoDB:
const { v7: uuidv7 } = require("uuid");
const { Binary } = require("mongodb");
function uuidToBinary(uuidStr) {
const hex = uuidStr.replace(/-/g, "");
const buf = Buffer.from(hex, "hex");
return new Binary(buf, Binary.SUBTYPE_UUID);
}
await collection.insertOne({
_id: uuidToBinary(uuidv7()),
name: "Alice"
});
ULID: An Alternative to UUID v7
ULID (Universally Unique Lexicographically Sortable Identifier) is an alternative format:
01ARZ3NDEKTSV4RRFFQ69G5FAV
^ ^^
10-char 16-char random
timestamp
import { ulid } from "ulid";
const id = ulid(); // "01ARZ3NDEKTSV4RRFFQ69G5FAV"
// With specific timestamp
const id2 = ulid(Date.now());
ULID vs UUID v7:
| Feature | ULID | UUID v7 |
|---|---|---|
| Format | Base32 | Hex with dashes |
| Length | 26 chars | 36 chars |
| Timestamp resolution | 1ms | 1ms |
| RFC standard | No | RFC 9562 |
| Database support | Library only | Native in PG 17+ |
| URL-safe by default | Yes | Yes (no special chars) |
UUID v7 is now preferred due to RFC standardization and native database support.
NanoID: Compact Random IDs
When you need short, URL-safe random identifiers instead of UUIDs:
import { nanoid } from "nanoid";
const id = nanoid(); // "V1StGXR8_Z5jdHi6B-myT" (21 chars)
const shortId = nanoid(10); // "IRFa-VaY2b" (10 chars)
NanoID uses A-Za-z0-9_- (64 characters), making IDs URL-safe. At 21 characters it has the same collision probability as UUID v4.
Try It Now
Generate UUID v4, v5, and v7 with the UUID Generator Tool. Generate NanoIDs and ULIDs with their dedicated tools.