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:

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.

Try it: need a batch of UUIDs right now? Our free UUID Generator mints version 4 UUIDs in bulk, in your browser.