Back to all posts
10 min read

Breaking Chains: Why I Dropped Rails 7.1 Support in state_machines-activerecord 0.40.0

Breaking Chains: Why I Dropped Rails 7.1 Support in state_machines-activerecord 0.40.0

Note: This post contains strong opinions formed after 12 years of battle in open-source trenches. Reader discretion advised.

Today, I released state_machines-activerecord 0.40.0. With it, I dropped support for Rails 7.1.

This marks a new era for the project—and a departure from the doctrine of eternal backward compatibility.

A Confession

Here’s a secret: when I started maintaining state_machines, I didn’t author it. The original gem was state_machine, but the original maintainer left. Burned out, or something worse. It was a giant monolith that monkey patched the universe. All the plugins crammed into a single codebase, sometimes in single files.

I took it over 12 years ago. Split it up. Made it modular. Thousands of applications now depend on it. I’ve never enabled donations or sponsorships because for me, open source is about building a legacy… sending a message to myself. Because at the end of the day, I can see what I did.

I’ve watched projects that took money, then the maintainer developed Pavlov syndrome. They only react when tipped. It’s not evil, it’s just how the basic brain is wired. LLMs work exactly the same way, by the way.

The Moment Everything Changed

I was already burned out. I reached out to the JRuby team to share my frustration about dropping support for outdated versions. I discovered they’d already left Java 8 behind and jumped straight to Java 21. I wasn’t expecting that. Going from 8 to 21 felt like upgrading from a Game Boy straight to a PlayStation 5—exciting, but I didn’t even know where to insert the cartridge.

But then one of them told me that a deprecation I tried to remove was authored for Java 1. That’s 1996. Nearly 30 years ago.

That moment reinforced what I’d been feeling: legacy is killing us.

The Real Cost of Forever

For years, I believed backward compatibility was sacred. I thought there was wisdom in supporting every version, that breaking changes were a sign of immaturity.

But here’s what two decades taught me: Forever backward compatibility kills innovation.

When you maintain a library long enough, your brain rewires itself around its patterns. You know every corner of the system inside out. You see where it’s slow, where it’s bloated, where you could cut out half the code and make it twice as fast. We maintainers have our own context windows too. That’s why when someone tells me they have “10 years of Rails experience,” I’m not impressed. Too often it just means they learned rails new a decade ago and never evolved.

The Archaeology of Features

Let me show you the math that broke me:

Adding a new feature: 3 lines of code.
Making it compatible with 5+ Rails versions: 190 lines of conditions, guards, and monkey patches.

Every feature request became an exercise in archaeology. Instead of asking “How can we make this better?” I was asking “How can we make this work with Rails 6.2 and Ruby 3.0?”

I remember when a junior developer wanted to help. I got frustrated because they couldn’t understand that in legacy Rails there’s no before_action, only before_filter. That callbacks fired differently. That they had to reimplement or monkey patch mechanisms to upgrade old versions, even though it’s an exact replica of what’s in the new version.

The Emails That Never Stop

You know what happens when things break? I get emails. Angry emails from people who think I monkey patched their entire world. Not just to my public email, but across all my addresses. They buy them from data brokers. (And no, I’m not throwing an ad for those removal services, they’re pure vaporware.)

Because tools like Sentry show them a stack trace from my gem, but don’t tell them: “BTW, the overridden code is identical to the new Rails version, so maybe you’re using the gem incorrectly.”

The Retreat

So what happened? I started building my own stuff in private, away from the constant pings and opinions and advice, especially from talkers not doers. I let some gems rot by muting notifications.

From time to time, I’d open GitHub, see a PR that made sense, merge it. Boom. Half the audience complains that it broke their flow. PRs to revert follow immediately. I revert. More issues. Turns out the person who submitted the revert accidentally changed other stuff that only worked on their machine.

Why Rails 7.1 Had to Die

Rails 7.1 is already obsolete. Rails 7.2 has been out for months. Rails 8 is here. Yet I was still writing compatibility shims in gems for a version that Rails itself has moved past.

I’ve seen teams of 20 developers maintaining Rails 4.2 applications in critical infrastructure. Not because they can’t upgrade—because they won’t. They’ve built entire bureaucracies around managing technical debt instead of paying it down.

I once upgraded an app from Rails 5 to 7.2 in one week. This was before AI was around. A colleague complained to management that I was “impossible to work with” and it was “affecting his morale.” Why? Because code was getting refactored. Because dead code was getting deleted. They let me go—not for lack of skills, but because I didn’t “communicate step by step” what I was doing.

I’m thinking: if your team can’t follow a Rails upgrade, maybe they learned development from YouTube tutorials. They’re copy-paste artisans, crafting software through the gentle art of Ctrl+C, Ctrl+V.

When your state machine is 10,000 lines of nested IF-ELSE statements, the problem isn’t the library. When you need a month of meetings to decide whether to use a gem, the problem isn’t the gem.

These teams aren’t my target audience anymore. They can fork if they want—though they’ll probably need a YouTube tutorial for that too.

”But What About…”

I know what you’re thinking. I’ve heard every excuse:

“But we have regulatory requirements!”
No, you don’t. Your regulator doesn’t care if you use Rails 4.2 or Rails 8. They care if your system is secure. And guess what? That 10-year-old framework full of unpatched vulnerabilities isn’t helping your compliance.

“But our budget won’t allow upgrades!”
Your budget allows for 20 developers to maintain legacy code. Your budget allows for monthly meetings about meetings. Your budget allows for consultants who bill $500/hour to tell you what you already know. But somehow upgrading Rails is too expensive?

“But it works fine as is!”
So did asbestos. So did lead paint. “It works” is not the same as “it should exist.” Your code works the same way a Moroccan taxi Mercedes 190 with 2 million kilometers still “works.” Sure, it moves. But at what cost?

“But we have custom modifications!”
Translation: we monkey patched core functionality instead of contributing upstream or reconsidering our approach. This isn’t a reason to stay on old versions. It’s a confession that you’ve been doing it wrong.

Why This Matters

Some of you are thinking: “Why is he making such a big deal about dropping a version? Just do it.”

Well, when you do open source, you lose the luxury of “it works on my machine” or “it works on my server.” You start seeing the wider picture. You know that thousands depend on your gem. You can drop jokes in the comments, but you can’t refactor stuff and drop features or interfaces overnight.

That’s why it took me 3 years to support kwargs in the state machine. Not because it was impossible, but because I had to refactor over 100 places and ensure tests passed. AI helped with automation, thankfully. Oh, and you also need to test on TruffleRuby, JRuby, and a matrix of Ruby versions going back to the time of Jesus Christ.

But that’s not all. I also needed to test that it didn’t break the plugins, or break extensions not even in the state_machines org. That meant I had to either contribute there or sync with those developers.

Removing versions just like that breaks other people’s flow. Especially when they’re also testing against a matrix of Ruby versions.

Then you start receiving notifications of being mentioned in repos you didn’t even know existed. You read the comments, and sometimes they’re angry, upset. Sometimes they switch languages mid-rant. That’s when you know a developer hit peak frustration—when they abandon English entirely, reaching for languages better suited to venting developer rage. Like Klingon.

A New Philosophy

Here’s my new approach:

  • Support current Rails and one version back
  • Drop support aggressively when versions are superseded
  • Focus on features over compatibility
  • Let the code breathe

Think about it: if your architecture is built on a house of cards, that means two things. Either you didn’t follow conventions, or you’re monkey patching the galaxy instead of contributing back. Or you’re not engineering, just vibing without code.

These are the people who gaslighted us for decades, trying to make us think that staying on the same version is a virtue.

Look at Linux. It’s much older than your app, and you can upgrade it version by version to the latest release. Why? Because when Linus built it, he had a vision and stuck with it for decades. Your app is shit only if you started as an ecommerce to take down Shopify because of a weekend hangover, then realized maybe you should pivot to food delivery with the same codebase.

The Future We Could Have

By dropping Rails 7.1, I can finally implement features that have been waiting for years:

  • Cleaner async state transitions
  • Better ActiveRecord 7.2+ integration
  • Performance improvements that modern Ruby enables
  • Simpler, more maintainable code

This isn’t about abandoning users. It’s about serving the ones who are building tomorrow, not maintaining yesterday.

The Choice

But first, let me acknowledge the heroes: the maintainers who upgrade regularly, the developers who contribute fixes upstream, the teams who understand that software evolves. You’re the reason I still do this after 12 years. This change is for you.

After 20 years, I’ve learned that the best code is code that evolves. The best libraries are ones that push their users forward, not ones that enable stagnation.

Think about it: React forced everyone to rethink jQuery spaghetti. Rails itself killed the “it works on my Apache” mentality. Rust made us question why we accepted memory leaks as normal. These tools succeeded not by coddling legacy code, but by showing a better path forward.

state_machines-activerecord 0.40.0 is leaner, faster, and ready for the future.

The past has enough monuments. Let’s build something new.

Migration Guide

If you’re affected by this change:

  1. Option A: Upgrade to Rails 7.2 or 8.0 (recommended)
  2. Option B: Pin your Gemfile to gem 'state_machines-activerecord', '~> 0.39.0'
  3. Option C: Fork and maintain your own compatibility layer

For detailed migration instructions, see the CHANGELOG.

My Mission Is Clear

My mission is clear: to make programming with Ruby fun again.

Over the coming weeks and months, I’ll be releasing a series of new gems designed specifically to spark joy, simplify complexity, and inspire developers to build better, cleaner Ruby code.

I’ve done this before—but differently. Previously, I’ve released gems that others took over for short-term gain, boosting their own careers or companies. These gems ended up orphaned, their Rubygem namespaces reserved, documentation abandoned, code untouched for years.

Not anymore. This time, I’ll share these projects directly—through Hacker News, on X, via friends—and actively engage with the Ruby community. These won’t just be five-minute-fame gems; they’ll be crafted for long-term value, maintained openly, and guided by my original vision.


state_machines-activerecord 0.40.0 is available now. Rails 7.1 users: pin to 0.39.x. Everyone else: welcome to the future.

Start with an engaging introduction that hooks the reader.

Main Content

Add your main content sections here.

Conclusion

Wrap up with key takeaways and next steps.

🔗 Interstellar Communications

No transmissions detected yet. Be the first to establish contact!

• Link to this post from your site• Share your thoughts via webmention• Join the IndieWeb conversation

Related Posts