← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

UUID vs ULID vs Auto-Increment

database PHP 7.0+ Intermediate

Also Known As

UUID ULID primary key UUID v7 auto-increment

TL;DR

Primary key strategies: auto-increment is simple and fast, UUID v4 is globally unique but random (poor index performance), UUID v7 and ULID are sortable globally unique IDs.

Explanation

Auto-increment (BIGINT): simple, compact, sequential — poor for distributed systems (coordination needed). UUID v4: globally unique, no coordination, but fully random — causes B-tree index fragmentation and poor cache locality. UUID v7 (2023): UUID format with millisecond timestamp prefix — sortable, globally unique, good index performance. ULID: 26-char Base32, timestamp-sortable, URL-safe. For most PHP apps: BIGINT auto-increment for internal tables, UUID v7 or ULID for externally visible IDs (APIs, URLs). MySQL uses utf8mb4 for UUID storage; PostgreSQL has a native uuid type.

Common Misconception

UUID v4 is the best choice for globally unique IDs — UUID v4's randomness causes B-tree index fragmentation and poor INSERT performance at scale; UUID v7 or ULID are better alternatives.

Why It Matters

Switching from auto-increment to UUID v4 on a high-write table can reduce INSERT throughput by 50%+ due to index fragmentation; UUID v7 gives global uniqueness without the performance penalty.

Common Mistakes

  • UUID v4 as primary key on high-write tables — random inserts fragment the B-tree index.
  • Storing UUIDs as VARCHAR(36) instead of BINARY(16) or native uuid type — 3× the storage and slower indexes.
  • Exposing auto-increment IDs in URLs — reveals business data (order count, user count) and enables enumeration.
  • ULIDs not sorted correctly in PHP — use a ULID library that returns lexicographically sortable strings.

Code Examples

✗ Vulnerable
-- UUID v4 as PK — random, index-fragmenting:
CREATE TABLE orders (
    id VARCHAR(36) PRIMARY KEY DEFAULT (UUID()),  -- Random, large, slow
    total DECIMAL(10,2)
);
-- 1M inserts: B-tree constantly reorganised, cache misses everywhere
✓ Fixed
-- UUID v7 (sortable) or ULID:
CREATE TABLE orders (
    id BINARY(16) PRIMARY KEY,  -- UUID v7: timestamp-prefixed, efficient
    total DECIMAL(10,2)
);

-- PHP with ramsey/uuid:
use Ramsey\Uuid\Uuid;
$id = Uuid::uuid7()->toString(); // 01956b3c-...: sortable, globally unique

-- Or ULID:
$id = (new Ulid())->toRfc4122(); // 01J3K2... — timestamp sortable

Added 15 Mar 2026
Edited 22 Mar 2026
Views 24
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping W 0 pings T 0 pings F 2 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 3 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 1 ping M 0 pings T 0 pings W 1 ping T
No pings yesterday
Amazonbot 8 Perplexity 4 Unknown AI 2 SEMrush 2 Majestic 1 Google 1 Ahrefs 1
crawler 19
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Use UUIDv7 (time-ordered) or ULID instead of UUIDv4 for primary keys — random UUIDs fragment B-tree indexes causing write performance degradation on large tables
📦 Applies To
PHP 7.0+ web cli queue-worker laravel
🔗 Prerequisites
🔍 Detection Hints
UUIDv4 as primary key on high-write table causing InnoDB index fragmentation; auto-increment exposing record count via URL
Auto-detectable: ✗ No percona-toolkit mysql-slow-query-log
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Low ✗ Manual fix Fix: Medium Context: File Tests: Update

✓ schema.org compliant