UUIDs vs Auto-Increment IDs: Which Should You Actually Use?
September 29, 2026 · 6 min read
Every new project starts the same way: you create a users table, and then you stare at the id column for slightly too long. Auto-increment integer, like everyone has done since forever? Or one of those long UUID strings, like the cool distributed-systems kids use? People have shockingly strong opinions about this. Here's my honest take after using both in production: it depends, but the decision is simpler than the internet makes it sound.
What each one actually is
An auto-increment ID is a plain integer the database assigns: 1, 2, 3, … It's tiny (4 bytes), human-friendly, and sorts naturally. A UUID (Universally Unique Identifier) is a 128-bit value usually written as 32 hex digits in groups — 550e8400-e29b-41d4-a716-446655440000. Version 4 UUIDs are randomly generated, which means any machine can mint one without asking a central authority, and the chance of two colliding is so astronomically small you can ignore it.
The case for auto-increment
For a single database serving one application, auto-increment wins on almost every axis. It's 4 bytes versus 16, so indexes are smaller and faster. It's sequential, so new rows append neatly to the index instead of scattering randomly across it (random UUIDs as primary keys can genuinely hurt write performance on large tables — this isn't theoretical). It's readable: "user 42" means something in a support conversation; "user 9f3b2a1e-…" does not. And debugging is just nicer when IDs are small numbers.
If you're building a standard web app with one database, stop here. Use auto-increment. You're done, and your database will thank you.
The case for UUIDs
UUIDs earn their keep in specific situations:
- Multiple writers. Two services, or a phone app working offline, both creating records that later merge into one database. With auto-increment, both sides mint "id 5" and you have a collision. With UUIDs, each side generates globally unique IDs independently. No coordination needed.
- Security through unpredictability.
/orders/1042invites curious users to try/orders/1043— and see someone else's order. Sequential IDs leak your growth rate too (competitors love that). UUIDs in URLs aren't real access control — you still need auth checks — but they remove the trivial enumeration attack. - Generating IDs before inserting. Sometimes you need the ID before the row exists — to name an uploaded file, to reference the record in a message queue, to return it in an API response optimistically. UUIDs let the application create the ID; auto-increment forces a database round-trip first.
- Merging databases. Acquisitions, sharding, multi-region setups. Joining two tables of auto-increment IDs is a renumbering nightmare. UUID tables merge cleanly.
The downsides nobody mentions until it's too late
UUIDs aren't free. Beyond the storage and index-fragmentation costs: they're miserable in URLs (/invoices/9f3b2a1e-7c4d-4e8f-b2a1-3d5f6a7b8c9d), miserable in logs, and miserable when a customer reads one over the phone. And there's a subtle one — random UUIDs reveal nothing, which sounds good until you're debugging and can't tell which of two identical-looking records was created first. (UUID v7, which embeds a timestamp, fixes this and is worth a look if you're on team UUID.)
Auto-increment's downsides are mostly about scale and exposure: painful sharding, enumerable URLs, and the information leak of "we have 1.2 million users." For most apps, these never matter.
My actual rule of thumb
Default to auto-increment. Reach for UUIDs when you have a concrete reason — offline-first clients, multi-writer architectures, or public-facing IDs you don't want enumerated. "We might need to scale someday" is not a concrete reason; it's a way to pay distributed-systems taxes on a single-server app. And if you do use UUIDs as primary keys at scale, look into UUID v7 or store them as binary(16) — your future self will appreciate it.
The unpopular truth: most of the heated debates about this are between people solving different problems. A side project and a multi-region SaaS genuinely want different answers, and both are right.