·10 min read·Developer Tools

UUID v4 vs v7 vs ULID: Which ID Format Should You Use?

Compare UUID v4, UUID v7, ULID, and NanoID. Learn the differences in randomness, sortability, size, and performance. Choose the right identifier for your database and API.

Try our free UUID / ULID Generator

Generate UUID v4, v7, and ULID. Bulk generate up to 1,000 IDs at once.

Open Tool

Why Your ID Format Matters

Every record in your database needs an identifier. The format you choose affects query performance, index efficiency, storage size, and even security. Auto-incrementing integers are simple but leak information (competitors can estimate your user count) and cause conflicts in distributed systems.

Unique identifiers like UUIDs solve the distributed generation problem — any node can create an ID independently without coordination. But not all UUID versions are equal. The classic UUID v4 (random) has well-documented performance problems with B-tree indexes that UUID v7 and ULID were specifically designed to solve.

In 2024, RFC 9562 formally standardized UUID v7, giving developers an official time-sortable UUID that combines the universality of UUIDs with the database performance of sequential IDs. This guide compares all the major options so you can make an informed choice. Generate any format instantly with our UUID / ULID Generator.

UUID v4: The Random Standard

UUID v4 has been the default choice for over two decades. It generates 122 bits of cryptographically random data, formatted as 32 hexadecimal characters with hyphens: 550e8400-e29b-41d4-a716-446655440000.

Strengths

  • Universal support — Every language, database, and framework supports UUID v4. It is built into PostgreSQL, MySQL 8+, Node.js (crypto.randomUUID()), Python, Java, Go, and more.
  • No coordination needed — Any machine can generate a UUID v4 independently with virtually zero collision risk.
  • No information leakage — Since v4 is purely random, it reveals nothing about creation time, sequence, or the generating machine.

Weaknesses

  • Poor index performance — Random values scatter inserts across the entire B-tree index, causing page splits and cache misses. This can degrade write throughput by 2-10x compared to sequential IDs at scale.
  • Not sortable — You cannot determine creation order from UUID v4 values. If you need chronological ordering, you need a separate timestamp column and index.
  • Large storage size — 36 characters as a string, 16 bytes as binary. This adds up in tables with billions of rows and multiple foreign key references.
// Generate UUID v4 in JavaScript (built-in, no library needed)
const id = crypto.randomUUID();
// → "f47ac10b-58cc-4372-a567-0e02b2c3d479"

// In Node.js
import { randomUUID } from 'crypto';
const id = randomUUID();

UUID v7: Time-Sorted and Modern

UUID v7 (RFC 9562, May 2024) solves the index performance problem by embedding a Unix timestamp in milliseconds in the first 48 bits. The remaining bits are random, preserving uniqueness and unpredictability for the sub-millisecond component.

The structure is: [48-bit timestamp][4-bit version][12-bit rand_a][2-bit variant][62-bit rand_b]. Because the timestamp occupies the most significant bits, UUID v7 values naturally sort in chronological order when compared as strings or bytes.

Why UUID v7 Is Better for Databases

In a B-tree index (used by PostgreSQL, MySQL, SQLite, and most databases), new UUID v7 values always insert near the end of the tree because they contain an increasing timestamp. This means:

  • No random page splits — writes are sequential, like auto-increment
  • Better cache hit rates — recently inserted pages stay in memory
  • Range queries by time are free — WHERE id > [uuid-from-yesterday] works
  • No separate created_at index needed for chronological queries
// Generate UUID v7 in JavaScript (using 'uuidv7' package)
import { uuidv7 } from 'uuidv7';
const id = uuidv7();
// → "018f8c3e-5b2a-7def-8a1c-4f3e2d1a0b9c"
//    ^^^^^^^^^^^^^ timestamp portion (sortable)

// Extract timestamp from UUID v7
function getTimestamp(uuid7: string): Date {
  const hex = uuid7.replace(/-/g, '').slice(0, 12);
  const ms = parseInt(hex, 16);
  return new Date(ms);
}

ULID: Compact and Sortable

ULID (Universally Unique Lexicographically Sortable Identifier) was created in 2016 as an alternative to UUID with better ergonomics. It encodes 128 bits using Crockford Base32, producing a 26-character string like 01ARZ3NDEKTSV4RRFFQ69G5FAV.

The structure is: [48-bit timestamp (10 chars)][80-bit randomness (16 chars)]. Like UUID v7, the timestamp is in the most significant bits, so ULIDs sort chronologically. The Crockford Base32 encoding is case-insensitive and avoids confusing characters (I, L, O, U).

ULID vs UUID v7 — Which to Pick?

  • Size advantage — ULID is 26 characters vs UUID's 36. That is 28% shorter in string form, which matters in URLs, logs, and API responses.
  • No hyphens — Easier to select with a double-click, copy from terminal output, and use in file names.
  • Monotonic option — ULID libraries can generate monotonically increasing values within the same millisecond, guaranteeing sort order even under high throughput.
  • Weaker ecosystem — ULIDs are not an RFC standard. Fewer databases have native ULID types. You may need to store them as strings or convert to binary.
// Generate ULID in JavaScript
import { ulid, decodeTime } from 'ulid';

const id = ulid();
// → "01H5T3K9V2RNGE8AQ1YDMZ6XCW"

// Extract creation timestamp
const timestamp = decodeTime(id);
// → 1690000000000 (Unix ms)

Head-to-Head Comparison

FeatureUUID v4UUID v7ULID
Size (string)36 chars36 chars26 chars
Size (binary)16 bytes16 bytes16 bytes
Time-sortableNoYes (ms)Yes (ms)
Random bits1227480
StandardizedRFC 9562RFC 9562Community spec
DB index perfPoorExcellentExcellent
Native DB typeUUIDUUIDString/Binary
Embeds timestampNoYesYes
Case sensitiveNo (hex)No (hex)No (Base32)

Generate and compare all three formats with our UUID / ULID Generator. You can also check exact timestamps embedded in IDs using the Timestamp Converter.

Decision Framework: Which to Choose

Use this decision tree:

  • Use UUID v7 if: You are building a new application, want database performance + time-sorting, need compatibility with existing UUID columns/types, and want an RFC-standard format. This is the default recommendation for most new projects in 2026.
  • Use ULID if: You want shorter IDs (26 chars), need IDs in URLs or user-facing contexts, want monotonic ordering within the same millisecond, or are building in an ecosystem that already uses ULIDs.
  • Use UUID v4 if: You need maximum unpredictability (security-sensitive contexts where timestamp leakage is a concern), are working with legacy systems that specifically expect v4, or do not have write-heavy workloads where index performance matters.
  • Use NanoID if: You need even shorter IDs (21 chars by default, customizable), are generating client-side IDs in the browser, or need a custom alphabet. Note: NanoID is not time-sortable.

For most applications in 2026, UUID v7 is the best default choice. It gives you the universality and tooling support of UUIDs with the performance characteristics of sequential IDs. If your database is PostgreSQL, you can store UUID v7 in a native uuid column with no changes to your schema.

Frequently Asked Questions

What is the difference between UUID v4 and UUID v7?
UUID v4 is fully random (122 random bits). UUID v7 embeds a Unix timestamp in the first 48 bits followed by random bits, making it naturally sortable by creation time and dramatically better for database index performance.
Should I use UUID or ULID for my database?
If you need an industry standard with broad library support, use UUID v7. If you want shorter IDs (26 vs 36 chars) with the same sortability, use ULID. Both embed timestamps for chronological sort order.
Can UUID v4 have collisions?
Practically no. With 122 random bits (5.3 x 10^36 possible values), you'd need to generate ~2.7 billion UUIDs per second for 100 years for a 50% collision probability. Collisions are not a real-world concern.
Why are random UUIDs bad for database performance?
Random UUIDs cause B-tree index fragmentation — new inserts land at random positions, causing page splits and poor cache utilization. Time-sorted IDs (v7, ULID) always append to the end of the index, maintaining sequential write performance.

Generate UUIDs and ULIDs Instantly

Generate UUID v4, v7, and ULID. Bulk generate up to 1,000 IDs. Copy individually or as a list. Free and private.

Open UUID / ULID Generator

Related Articles

Related Tools