UUID vs ULID vs Auto-Increment
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
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
22 Mar 2026
Views
24
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 1
No pings yesterday
Amazonbot 8
Perplexity 4
Unknown AI 2
SEMrush 2
Majestic 1
Google 1
Ahrefs 1
Also referenced
How they use it
crawler 19
Related categories
⚡
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