Rails 5.0 is approaching, bringing with it niceties for websockets, backend-only API servers, and revamping the command layer. Version 4.0 brought turbolinks, russian-doll caching, the queue API, and a host of improvements. All of these, except maybe turbolinks, were great new features but did not fundamentally alter the way applications are built in Rails. That’s good news! It means Rails is a mature and thriving platform. But it’s also bad news, because there are fundamental limitations which are most likely unsolvable in Rails as we know it. To resolve that paradox, it’s worth taking a trip in time.

The Past

It may be difficult for developers coming onto the scene now to understand how radical Rails was when it arrived on the scene over a decade ago. It piled heresy upon heresy: it rejected both the bureaucracy of Java, and the chaos of PHP. It made no effort to be modular, imposing its notion of how things should work on the programmer rather than letting her make every minuscule decision. Perhaps most shocking of all, it cared more about feelings than performance, or encapsulation, or simplicity of implementation, or anything else a good engineer is supposed to care about.

The reaction was, to put it mildly, polarizing. For some of us, it was a bolt of lightning, a moment of clarity. I never wrote any PHP (and still haven’t) so I can’t tell you how it felt to come from PHP, but coming from Java it was like the first time I wore glasses: there was a whole world I didn’t know I was missing. Patterns we followed in Java, like Model/View/Controller and Active Record, were suddenly clean, simple, obvious, default, and free of ceremony. They were just the only natural way to work. Unit tests were laborious and verbose in Java, a task that only the most ardent disciples would undertake. With Rails, they were easy, and code generators removed most of the friction. And of course, the key enabler was Ruby itself, specifically the ease with which it let the programmer create domain-specific languages (DSLs) that look and feel like first-class features of Ruby itself. Seamless DSLs were and are central to every part of Rails, and they were more or less unknown outside the Lisp community in 2005.

But some people hated Rails and Ruby. Hated them. Something about it caused visceral reactions, positive or negative. The hatred was often well-grounded. DSL magic can obscure what the code is actually doing. Performance does matter. And though those of us in the “love” camp might have argued with it at the time, the haters were not all wrong. Those things do matter, and Rails succeeded in spite of them, because the unique things it offered were so unbelievably liberating.

What did it offer? Permission to care about how the code looks and feels. Flow. Ability to write code like prose, in a continuous stream. A community united by a single dominant framework, so that everything anybody wrote in Ruby had to take it into account. Things we take for granted now, but revolutionary at the time.

It changed the dev world dramatically. Copycat frameworks in other languages, aiming to get the goodies without Ruby’s limitations, sprung up quickly. Most managed to replicate several of those advantages; some have been quite successful. But none of them blew up the way Rails did, because they could never quite match the synergy (yeah, that’s right, I said it) that Rails achieved in combining all those factors into one place. Django, Grails and others entered into a landscape filled with partisans of other frameworks, whereas Rails singlehandedly cast Ruby into the mainstream and benefitted from the network effects that go with that. You can make a DSL in any language, but few can match Ruby’s ability to feel like part of the base language.

You may have noticed that feelings keep coming up.

Of course, there was a price. Rails could certainly scale, but poor performance meant that it was forced to scale quite a bit sooner than other languages. Developer time certainly is more expensive than servers, but only up to a point. Perhaps more damningly, as Rails projects got larger, they would tend to get harder and harder to maintain. The power that made it an excellent tool for people who had already been burned by bad habits made it a nightmare in less-disciplined hands. There was an explosion of DSL-oriented libraries that sometimes coexisted poorly with each other. Old libraries were quickly abandoned in favor of new ones in the name of smaller and more subjective improvements in readability. A culture of magic made debugging difficult. Unit tests, which were a requirement for sanity in the absence of static types, got slower and slower. Opinionated software is great until you get to the one thing you really do need to do differently.

The Present

So here we are in 2016. Certainly older; hopefully wiser. We’ve watched some of these problems get solved. There are a few which never did get solved, and are likely never to be solved satisfactorily, but we’ve stuck with it, because those core advantages still matter.

The world is now very different.

First, the free lunch from Moore’s law is over. There was an inflection point in 2005 when single-threaded CPU performance reached a point just high enough to make very slow languages like Ruby viable, but we can no longer count on that improving. It is certainly possible to get Rails to take advantage of multiple cores, but it’s inefficient and expensive. A better, easier, more automatic way to get benefit from multiple cores is overdue.

Second, the huge success of Rails means that there are many very large projects out there. The way that Ruby accomplishes its magic, by dynamically building up structures every time, presents some fundamental problems in large projects, in the form of slow start times, subtle load-order issues, and slow builds that make effective testing painful.

Third, Rails has successfully convinced a lot of people that its philosophy is right. Thus, there’s a lot of energy devoted to creating the Next Big Thing; the framework that gives us what we love about Rails; the language that enables it like Ruby did while addressing their shortcomings and setting us up for the future.

That framework is Phoenix and that language is Elixir.

The Future

Using Phoenix now is the first time I’ve had that same feeling since; that bolt from the blue feeling of rightness that I had when I first experienced Rails in 2005. It’s the first one to replicate that look and feel. But it’s also fast, and concurrent down to its very bones. It gives you the magic in a way that you can control. And it’s the Next Big Thing.

Don’t mistake me: this is not a prediction. I don’t have a crystal ball. It’s a commitment to make it come true.

I have been making software with Rails and Ruby non-stop for over a decade. Several of my colleagues have been at it for at least as long. We love Rails and we will keep using it where it’s appropriate — long may it reign! — but our future is Phoenix, and the time to build it is now.

We’ll be writing in detail over the coming weeks and months about why we’re convinced and what our experiences have been at Infinite Red. To read more, follow our publication. Stay tuned.