Auto-Increment Integer vs UUID as Primary Key
Fast recall
Quick revision
Core answer
Understanding the performance implications of sequential versus random primary keys, including index fragmentation, storage size, and distributed system requirements
Using random UUID version 4 as a primary key without understanding the B-tree index fragmentation problem that causes page splits and degrades insert throughput
Compare where identifiers are generated, index locality and size, merge requirements, and measured database cost; UUIDv7 improves time ordering but is not identical to a database sequence
Interview-ready guide
Interview answer
Auto-increment integers and UUIDs solve different id-generation needs.
A BIGINT is compact and ordered, so it often gives a B-tree good insertion locality when one database assigns ids. A UUID is 16 bytes and can be created independently before a row reaches the database, which helps when records are created in several places or later merged.
Random UUIDv4 values spread writes across a B-tree and may increase page splits and cache pressure; the size of that effect must be measured rather than quoted as a fixed percentage. UUIDv7 is time-ordered and usually improves locality, though it is still not the same as a database sequence. In PostgreSQL, store UUIDs in the native uuid type.
Choose from generation, merge, exposure, and measured index needs—not from a universal monolith-versus-microservices rule.
Auto-Increment Integer vs UUID as Primary Key
Direct Answer
Auto-increment integers are compact, simple, and naturally ordered, so they often work well when one database assigns IDs. UUIDs can be generated independently across services and are harder to guess, but they use more space; random UUIDs can also reduce B-tree locality. Choose from the system's ID-generation, exposure, merge, and index needs rather than from a monolith-versus-distributed rule.
Code Example
-- PostgreSQL identity: small and ordered
CREATE TABLE orders (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
);
-- PostgreSQL UUID: independently generated and stored in its native type
CREATE TABLE events (
id UUID PRIMARY KEY
);
These are two valid designs. Pick after deciding where ids are created and checking the index and storage trade-offs on the database you actually use.
Common Mistakes & Pitfalls
- Ignoring UUIDv4 locality: Random UUIDs spread B-tree inserts across the key range and can increase page splits, index size, and cache work. Measure insert throughput and index behavior on the real schema instead of quoting a fixed penalty or an unrelated table statistic.
- Choosing from architecture labels: A single service may need independently generated ids, while a distributed system can also coordinate numeric ranges or sequences. Decide from generation and merge requirements rather than the words monolith or microservices.
- Using text when a native type exists: PostgreSQL's native
uuidtype stores a UUID in 16 bytes and validates its format. Text storage can still be necessary for portability, so compare the actual database and client requirements rather than treating one representation as universal.
Check your understanding
Answer these without looking back at the article.
- Why do random UUIDs cause B-tree fragmentation?
- What is UUID version 7 and why is it better for databases?
- When would you overflow an INT primary key?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.