The perils of UUID primary keys in SQLite

Why one popular ID choice turned a speedy database into a total mess

TLDR: The big finding: random UUID IDs made SQLite inserts about 10 to 12 times slower than simple number IDs because the database had to constantly reshuffle data. Commenters instantly split into camps — use newer UUIDv7, ditch UUIDs entirely, or just stick with the built-in row ID.

A nerdy database benchmark somehow turned into full-blown comment section reality TV. The original post showed that using random UUIDs — those long, messy strings apps often use as IDs — can make SQLite, a lightweight database used everywhere, dramatically slower. In the test, ordinary counting-number IDs flew along at about a million inserts per second, while random UUID version 4 IDs crawled to a pace that was roughly 10 to 12 times slower. The reason, in plain English: instead of filing new rows neatly at the end, the database has to keep shoving them into random spots and constantly reorganizing itself.

And wow, the replies did not keep calm. One camp basically yelled, “This is a UUIDv4 problem, not a UUID problem,” arguing that newer time-ordered UUIDv7 fixes most of the chaos if you store it in compact binary form. Another camp went even harder: UUIDs are wildly overused, and for a single database, plain big integer IDs are smaller, faster, and less likely to become a self-inflicted wound. Then came the skeptics asking the question that launched a thousand raised eyebrows: how is SQLite pumping out a million inserts a second at all?

The jokes were inevitable. One commenter sighed that the integer-versus-UUID fight is basically the database version of vim vs Emacs — an eternal geek war with no peace treaty in sight. Others floated the humble built-in row ID as the practical hero. In other words: the benchmark was interesting, but the real spectacle was the crowd turning primary keys into a blood sport.

Key Points

  • The article explains that clustered indexes store rows physically in key order, making random UUID4 inserts expensive because they disrupt B-tree locality.
  • In ordinary SQLite tables, an implicit 64-bit integer rowid acts as the clustered index, while WITHOUT ROWID tables use the declared primary key as the clustered index.
  • A benchmark inserting data into a table with an integer primary key reports about one million inserts per second across large row counts.
  • A corresponding benchmark using UUID4 values as a BLOB primary key in a WITHOUT ROWID table reports batch times that are roughly 10–12 times slower than the integer baseline.
  • According to the article's profiling diffgraph, the UUID4 case spends significantly more time on B-tree balancing and read/write activity, and the article proposes time-ordered UUID7 as a potential remedy.

Hottest takes

"UUIDs are way over used" — blopker
"This is worse than vim v eMacs" — pyuser583
"Wait how is sqlite doing a million inserts a second?" — dumbledorf
Made with <3 by @siedrix and @shesho from CDMX. Powered by Forge&Hive.