Rails 5.1: Default Primary Keys

A Bit of History…

Remember the Twitpocalypse? Back in 2009, Twitter ran out of Integers. Like most of us, they set up the primary key in their tweets table to be a 32-bit signed integer. Once they hit the magical number (2,147,483,647), servers were all but guaranteed to catch fire in the most spectacular fashion.

Just in the nick of time, however, they managed to migrate to using 64-bit integers and bought themselves a nice chunk of time (the max is now 9,223,372,036,854,775,807).

Now, I’m sure you’re thinking to yourself: “Self, should I be worried about this?” And some days, it may feel kind of silly to worry about ever having more than 2.1B rows in a single table. But Twitter was like you once and didn’t worry about it … until it was too late!

Well, worry yourself no more. Primary keys in Rails 5.1 are now big integers by default! 🎉

But why not UUID?

Hey, I love me some UUID’s. But their usage as primary keys is still debated in the community. So for this change, we opted for making a more sane default that was more widely accepted.

But don’t give up hope! You can default to using UUID’s for primary keys in generators if you want. I submitted that patch last year: https://www.mccartie.com/2015/10/20/default-uuid’s-in-rails.html

Migrate

Already have a table with 32-bit integer primary keys? It’s easy enough to migrate them:

$ rails g migration change_primary_key_to_bigint_on_users

Then…

change_column :users, :id, :bigint

Richard Baptist mentioned to me that he needed to run the following migration for MySQL 5.7:

change_column :users, :id, :bigint, unique: true, null: false, auto_increment: true

The usual warnings apply when doing this to a large table running in prouduction…consult your local DBA for side effects.

NOTE: If you perform this upgrade, make sure to update foreign keys as well. If your primary key and foreign keys don’t match, Postgres won’t give you any warnings – MySQL will break.

Rails Core Team FTW

This was a big change to make. A fellow Heroku co-worker (“Herokai” Pavel Pravosud ) kicked this off back in May with a change for Postgresql. Unbenknowst to me that Pavel had started with this work, I made my own change to include both MySQL and Postgresql (sorry, SQLite doesn’t do bigint primary keys). I was able to merge Pavel’s work into my own. Then began the difficult (yet satisfying) task of hashing out the finer points with the Rails core team. But looking back on it all and seeing the quality of the tweaks that were suggested, I’m really grateful for the back and forth.

So find yourself a Core Team member today and give them a hug. Tell them thanks for their tireless efforts. And stop worrying about whether or not your primary keys are going to run out.

Cheers!

Hi there, I'm Jon.

Writer. Musician. Adventurer. Nerd.

Purveyor of GIFs and dad jokes.