Javid
·13 min read

UUID Generator: How to Create Unique IDs (v4, v7, ULID, and More)

SelfDevKit ID generator showing UUID v4, v7, ULID, NanoID, and KSUID batch generation

What is a UUID?

A UUID (Universally Unique Identifier) is a 128-bit value used to identify resources without a central authority. Defined by RFC 9562, UUIDs enable distributed systems to generate identifiers independently with virtually zero risk of collision. The standard format is 32 hexadecimal digits in five groups: 550e8400-e29b-41d4-a716-446655440000.

Every backend service, every database table, every message queue needs identifiers. A good UUID generator gives you those identifiers instantly, without coordinating with a central server and without worrying about duplicates. But UUIDs are no longer the only option. Newer formats like ULID, NanoID, and KSUID solve problems that UUIDs were never designed to handle.

This guide covers the major UUID versions, explains when each one makes sense, compares them to modern alternatives, and shows you how to generate any of them in seconds.

Table of contents

  1. UUID versions explained
  2. Which UUID version should you use?
  3. Beyond UUIDs: ULID, NanoID, and KSUID
  4. How to generate UUIDs in code
  5. UUID collision probability: the actual math
  6. UUID as a database primary key
  7. UUID generator: SelfDevKit
  8. Frequently asked questions

UUID versions explained

RFC 9562 (published May 2024, replacing RFC 4122) defines eight UUID versions. Three matter for everyday development: v1, v4, and v7.

UUID v1: timestamp + MAC address

UUID v1 encodes the current timestamp and the generating machine's MAC address into the identifier. This means v1 UUIDs are unique across machines and sortable by creation time.

The problem? They leak your hardware address. Anyone who reads a v1 UUID can extract the MAC address of the machine that generated it. For internal tooling this might be acceptable. For public-facing APIs, it is a privacy risk.

f47ac10b-58cc-11e4-8c21-0800200c9a66
                              ^^^^^^^^^^^^
                              MAC address embedded here

UUID v4: purely random

UUID v4 is the most widely used version. It fills 122 of 128 bits with cryptographically random data, leaving 6 bits for version and variant markers.

550e8400-e29b-41d4-a716-446655440000
         ^^^^ version nibble = 4

No timestamp, no MAC address, no leaked metadata. Just randomness. This makes v4 the default choice when you need a unique identifier and nothing else.

UUID v7: timestamp + random (the new default)

UUID v7 is the newest practical version, introduced in RFC 9562. It combines a Unix timestamp in milliseconds (48 bits) with random data (74 bits). The result is an identifier that is both unique and chronologically sortable.

018f3c2b-7c5a-7b91-9c8e-2f1c4d3a9b12
^^^^^^^^ ^^^^ millisecond timestamp prefix

Why does sortability matter? Because B-tree indexes in databases perform dramatically better when inserts arrive in roughly sorted order. Random v4 UUIDs scatter inserts across the index, causing page splits and fragmentation. v7 UUIDs insert at the end, keeping the index tight.

The RFC itself recommends v7 over v1 and v6 for new implementations.

UUID v3 and v5: namespace-based (niche use)

UUID v3 (MD5) and v5 (SHA-1) generate deterministic IDs by hashing a namespace and a name together. Given the same inputs, they always produce the same UUID. This is useful when you need reproducible identifiers, for example, generating a consistent UUID from a URL or DNS name. In practice, most developers reach for v4 or v7 instead. If you do need deterministic IDs, prefer v5 over v3 since SHA-1 is a stronger hash than MD5.

Which UUID version should you use?

For most new projects, UUID v7 is the right answer. Here is a quick decision matrix:

Scenario Recommended version Why
Database primary key v7 Sortable, excellent index performance
API resource identifier v4 or v7 No metadata leakage, widely supported
Distributed event ordering v7 Timestamp prefix enables natural ordering
Legacy system compatibility v4 Universally supported across all libraries
Tracing and correlation IDs v7 Timestamp helps when debugging timelines
Client-side generation in browsers v4 crypto.randomUUID() natively generates v4

If you are starting fresh and your language or library supports v7, use it. You get everything v4 offers plus chronological ordering at zero extra cost.

If you need cryptographic secrets rather than identifiers, a UUID is the wrong tool. Use a dedicated secret generator or password generator instead.

Beyond UUIDs: ULID, NanoID, and KSUID

UUIDs are not the only game in town. Several alternative ID formats have emerged to address specific shortcomings.

ULID (Universally Unique Lexicographically Sortable Identifier)

A ULID is a 128-bit identifier encoded as 26 Crockford Base32 characters. The first 10 characters encode a 48-bit Unix timestamp in milliseconds; the remaining 16 encode 80 bits of randomness.

01ARZ3NDEKTSV4RRFFQ69G5FAV
^^^^^^^^^^ ^^^^^^^^^^^^^^^^
timestamp   randomness

Key advantages over UUID:

  • Lexicographically sortable as plain strings (no special comparators needed)
  • URL-safe with no hyphens or special characters
  • Case-insensitive, reducing human transcription errors
  • Monotonic ordering within the same millisecond (some implementations)

ULIDs are excellent for logging systems, event streams, and anywhere you want compact, sortable IDs without the hyphenated UUID format.

NanoID

NanoID generates URL-friendly identifiers using a cryptographic random number generator. The default output is 21 characters from a 64-character alphabet (A-Za-z0-9_-).

V1StGXR8_Z5jdHi6B-myT

At 21 characters, NanoID is roughly 40% shorter than a UUID while providing comparable collision resistance. The length is configurable; shorter IDs trade collision resistance for compactness.

NanoID fits well as session tokens, short URL slugs, and client-side identifiers where brevity matters.

KSUID (K-Sortable Unique Identifier)

KSUID uses a 160-bit structure: 32 bits for a timestamp (second precision, offset from a custom epoch of May 13, 2014) and 128 bits of random payload. The result is a 27-character Base62 string.

2G1jMfDNToSvCwiEHm7bJBfOI3c

The extra 128 bits of randomness (compared to ULID's 80 or UUID v7's 74) make KSUIDs especially resistant to collisions in high-throughput systems. They work well for event-driven architectures, Kafka message keys, and audit logs where you need both sortability and extremely high collision resistance.

Comparison table

Format Length Sortable Timestamp Bits of randomness Standard
UUID v4 36 chars No No 122 RFC 9562
UUID v7 36 chars Yes ms precision 74 RFC 9562
ULID 26 chars Yes ms precision 80 Community spec
NanoID 21 chars (default) No No ~126 (at 21 chars) Community spec
KSUID 27 chars Yes second precision 128 Community spec

SelfDevKit's ID Generator supports all five formats. Generate any of them instantly, in batches, and copy the results with one click.

SelfDevKit ID generator with UUID, ULID, NanoID, and KSUID generation

How to generate UUIDs in code

Most languages have built-in or standard library support for UUID generation. Here are the most common approaches.

JavaScript / TypeScript

Modern browsers and Node.js (v19+) support crypto.randomUUID() natively for v4:

// UUID v4 - built-in, no dependencies
const id = crypto.randomUUID();
// "3b241101-e2bb-4d5a-8c8b-0e3e8d907f72"

For v7 or other formats, use the uuid package:

import { v7 as uuidv7 } from 'uuid';
const id = uuidv7();
// "018f3c2b-7c5a-7000-9c8e-2f1c4d3a9b12"

Python

Python's standard library handles v1 and v4. For v7, use the uuid6 package:

import uuid

# v4 - cryptographically random
print(uuid.uuid4())
# 7c9e6679-7425-40de-944b-e07fc1f90ae7

# v1 - timestamp + MAC address
print(uuid.uuid1())
# f47ac10b-58cc-11e4-8c21-0800200c9a66

For v7 in Python, uuid6 provides a drop-in extension:

import uuid6

# v7 - timestamp-sortable
print(uuid6.uuid7())
# 018f3c2b-7c5a-7b91-9c8e-2f1c4d3a9b12

Note that Python 3.x's uuid.uuid4() uses os.urandom() under the hood, which draws from the operating system's cryptographic entropy pool. This is safe for identifier generation. Do not substitute random.randint() or similar non-cryptographic sources.

Rust

The uuid crate supports all major versions:

use uuid::Uuid;

let v4 = Uuid::new_v4();
let v7 = Uuid::now_v7();
println!("{}", v4); // random
println!("{}", v7); // time-sorted

Go

The google/uuid package is the standard choice. It supports v1, v4, v6, and v7:

import "github.com/google/uuid"

v4 := uuid.New() // v4
fmt.Println(v4.String())

v7, _ := uuid.NewV7() // v7 - time-sorted
fmt.Println(v7.String())

Command line

Most Unix systems include uuidgen:

# macOS / Linux
uuidgen
# outputs a v4 UUID

# Or use Python one-liner
python3 -c "import uuid; print(uuid.uuid4())"

When you need to generate IDs in bulk without writing code, or you want to quickly switch between UUID versions, ULID, NanoID, and KSUID, a dedicated tool is faster than scripting. SelfDevKit's ID Generator lets you pick a format, set a quantity, and generate instantly.

UUID collision probability: the actual math

"Will my UUIDs ever collide?" Short answer: no. Not in practice.

UUID v4 has 122 random bits, giving 5.3 x 10^36 possible values. Using the birthday problem approximation:

P(collision) ≈ n² / (2 × 2^122)

where n is the number of UUIDs generated.

UUIDs generated Collision probability
1 million ~10^-25
1 billion ~10^-19
1 trillion ~10^-13
2.71 quintillion 50%

To reach a 50% chance of a single collision, you would need to generate 1 billion UUIDs per second for about 86 years. At more realistic rates of thousands per second, the sun will burn out first.

The real risk is not random collision. It is implementation bugs: using Math.random() instead of a cryptographic RNG, seeding with predictable values, or running in a VM that snapshots and restores entropy state. If your UUID library uses crypto.getRandomValues() (browsers), /dev/urandom (Linux), or equivalent, collisions are not a practical concern.

For systems generating millions of IDs per second where even a theoretical risk is unacceptable, KSUID's 128 bits of randomness (versus UUID v4's 122) provides an extra margin of safety.

UUID as a database primary key

Using UUIDs as primary keys is common but comes with tradeoffs that every developer should understand.

The index fragmentation problem

B-tree indexes, used by PostgreSQL, MySQL, and most relational databases, work best with sequential inserts. When you insert a random UUID v4, the database must place it at an arbitrary point in the index tree. This causes:

  • Page splits: existing index pages get divided to accommodate the new entry
  • Write amplification: more disk I/O per insert
  • Cache misses: the working set of index pages grows unpredictably

On a table with millions of rows, random UUID primary keys can cause insert performance to degrade by 2-5x compared to sequential keys. The exact impact depends on your database, storage engine, and working set size.

The v7 solution

UUID v7's timestamp prefix means new IDs are always greater than previous ones (within millisecond precision). Inserts hit the rightmost leaf of the B-tree, just like auto-incrementing integers. You get the distributed generation benefits of UUIDs with the index performance of sequential keys.

CREATE TABLE orders (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),  -- v4, causes fragmentation
    -- vs
    id UUID PRIMARY KEY,  -- use v7 from application layer
    created_at TIMESTAMP NOT NULL
);

If your database supports native v7 generation (PostgreSQL 17+ has discussions around this), use it. Otherwise, generate v7 in your application layer and pass it to the database.

Storage considerations

A UUID stored as a string takes 36 bytes. Stored as binary (BINARY(16) in MySQL, UUID type in PostgreSQL), it takes 16 bytes. For tables with millions of rows, the difference in index size is significant. Always use the native UUID column type when available.

For more on hashing data and verifying integrity, see our hash generator guide. If you are building APIs that return UUIDs in JWT tokens, make sure you understand how token payloads work.

UUID generator: SelfDevKit

SelfDevKit's ID Generator supports all the formats discussed above in a single interface:

  • UUID v1, v4, v7 with standard RFC 9562 formatting
  • GUID with uppercase/lowercase options
  • ULID with Crockford Base32 encoding
  • NanoID with configurable length
  • KSUID with Base62 encoding

Batch generation

Need 50 UUIDs for a database seed script? Set the quantity and generate them all at once. Copy the entire batch to your clipboard with one click. No loops, no scripts, no pasting one at a time.

Analyze existing IDs

Pair the generator with SelfDevKit's ID Analyzer to decode IDs you encounter. Paste any UUID, ULID, or KSUID and the analyzer extracts the version, timestamp, variant, and other embedded metadata. Useful when debugging distributed systems where you need to know when and where an ID was created.

Offline and private

Every ID is generated locally on your machine using cryptographic randomness from your operating system. Nothing is sent over the network. This matters for development environments that operate behind firewalls or in air-gapped networks where online generators simply are not available.

SelfDevKit includes 50+ developer tools beyond ID generation. JSON formatting, Base64 encoding, regex testing, JWT decoding, and more, all offline, all in one app.

Download SelfDevKit to start generating UUIDs, ULIDs, NanoIDs, and KSUIDs without leaving your desktop.

Frequently asked questions

What is the difference between a UUID and a GUID?

A GUID (Globally Unique Identifier) is Microsoft's name for the same 128-bit identifier format. Functionally, UUIDs and GUIDs are identical. The only difference is convention: GUIDs are typically displayed in uppercase ({550E8400-E29B-41D4-A716-446655440000}), while UUIDs use lowercase. SelfDevKit's ID Generator supports both uppercase and lowercase GUID output.

Is UUID v4 secure enough for authentication tokens?

UUID v4 is unique but not a security token. It uses cryptographic randomness, which makes it unpredictable, but it was designed for identification rather than authentication. For session tokens or API keys, use a dedicated secret generator that produces higher-entropy values with configurable character sets.

Can two UUID v4 values ever be the same?

Mathematically, yes. Practically, no. With 122 random bits, you would need to generate about 2.71 quintillion UUIDs to reach a 50% collision probability. That is 1 billion per second for 86 years. Real-world collision risks come from broken random number generators, not from the math.

Should I use UUID v7 or ULID for database keys?

Both are timestamp-sortable and perform well as primary keys. UUID v7 is the better choice if you want an IETF standard (RFC 9562) and your stack already uses UUID column types. ULID is better if you need compact, URL-safe strings without hyphens. Either one avoids the index fragmentation problem of random UUIDs.

Related Articles

JWT Secret Key Generator: How to Create Secure Signing Keys
DEVELOPER TOOLS

JWT Secret Key Generator: How to Create Secure Signing Keys

Learn how to generate a JWT secret key that actually meets RFC 7518 requirements, plus the format decisions developers always get wrong.

Read →
Hash Generator Guide: MD5, SHA256, and Cryptographic Hashing Explained
DEVELOPER TOOLS

Hash Generator Guide: MD5, SHA256, and Cryptographic Hashing Explained

Learn how hash generators work and when to use MD5, SHA256, SHA512, or BLAKE. Understand hashing for file integrity, password security, and API authentication with practical examples.

Read →
Secure Password Generator: The Complete Guide to Creating Unbreakable Passwords
DEVELOPER TOOLS

Secure Password Generator: The Complete Guide to Creating Unbreakable Passwords

Learn how to generate truly secure passwords in 2025. Understand password entropy, strength analysis, and why offline generators are the only safe choice for your credentials.

Read →