UUID performance in databases
October 9, 2026 · 15 min read
UUID primary keys sit on a spectrum from fast (time-ordered, compact binary) to slow (random v4 in wide char columns). Performance dashboards rarely label the culprit “UUID” - they show rising page splits, buffer pool churn, and growing index size. This guide maps those symptoms to identifier choices so you can tune storage without abandoning globally unique IDs.
What to measure before changing ID strategy
- Insert QPS and p99 latency on the primary key index.
- Index size per million rows (bytes per key).
- Buffer pool / cache hit ratio on the PK index.
- Secondary index fan-out when FK columns are also UUID.
Baseline with your actual driver and column type - CHAR(36), BINARY(16), native UUID in PostgreSQL, or MongoDB BSON Binary subtype 04. Changing only the UUID version without fixing string storage often yields smaller gains than expected.
Random v4 vs time-ordered v7
UUID v4 scatters inserts across the B-tree because each key is uncorrelated. UUID v7 (and ULID) concentrate new keys on the right side of the tree, similar to auto-increment integers but without a single coordinator. Benchmarks on high-core MySQL and PostgreSQL often show lower page split rates and better sequential insert throughput with v7.
Read-heavy workloads with random point lookups by _id are less sensitive to version; the index depth dominates. Write-heavy event streams and multi-tenant SaaS signups benefit most from sequential UUID layouts.
String vs binary storage cost
Canonical string UUIDs use 36 bytes UTF-8 plus collation rules; binary uses 16 bytes payload. Smaller keys mean smaller indexes and fewer disk reads per lookup. In MongoDB, subtype 04 Binary is the compact default; string _id values inflate working set and encourage case-sensitivity bugs.
When migrating string to binary, plan a backfill and codec alignment - see MongoDB binary UUID explained and the MongoDB UUID converter for byte verification.
Index and schema design
Avoid redundant indexes on both string and binary representations of the same logical ID. Use covering indexes thoughtfully - UUID PK plus many secondary indexes multiplies write cost. For time-range queries, a separate created_at column may outperform inferring time from v7 bits in SQL unless you standardize on v7 extraction functions.
Tuning checklist
- Switch new rows to UUID v7 (or ULID) at the application generator.
- Store as BINARY(16) / BSON UUID subtype 04, not char(36).
- Align Java, .NET, and Node drivers on RFC byte order (subtype 04).
- Monitor index bloat; rebuild or reorg on schedule after bulk loads.
- Validate partner IDs before insert with a UUID validator tool.
FAQ
- Are UUIDs always slower than integers?
- Inserts can be slower with random UUIDs; v7 and binary storage narrow the gap. Integer still wins raw size but loses global uniqueness.
- Does PostgreSQL native UUID type help?
- Yes - 16-byte storage and efficient comparison vs text columns.
- When should I keep UUID v4?
- Moderate volume, strong need to hide creation order, or no measured index pain.
Related: Sequential UUIDs guide · UUID vs auto-increment · MongoDB UUID storage