Hacker News new | ask | show | jobs
by jensvdh 1868 days ago
Shopify and Airbnb were able to become multi-billion dollar companies mostly by running on Rails before it became unsustainable. I'd say Rails scaled pretty well.
1 comments

While true, I also remember watching a presentation about Shopify where they explained how they spent a whole year migrating to a newer Rails version.

Now, Shopify clearly has the capacity to pull this off. But a smaller company that initially bet on Rails and is now facing a mountain of tech debt might not. To be fair: it is possible to write Rails applications in a way that you don't couple every aspect of your application to Rails internals. But in certain crucial ways, Rails encourages doing exactly that - dragging the DB along your whole application, for example.

I've been a Rails developer for a couple of years and I left that ecosystem in no small part because a huge chunk of that community seems to treat "architecture" as a dirty word and monkeypatching as a solution for everything (and also indulges into making fun of PHP or Java a bit too much for my taste). Of course, everyone's experiences are different and you can do great stuff with Rails, but for me it's something I don't really want to go back to.

Airbnb has also been vocal about the multi year slog to dig themselves out of their Rails hole.
On the other hand, it probably also enabled them to get up & running with a MVP fairly fast and low-cost. No one knew it was going to be the big success from the get-go, and most new companies fail.

In hindsight, it was probably a bad choice. At the time however, it was probably a good one.

Besides, things like AirBnB are the exceptions. Most sites don't get anywhere near the traffic they get, and Rails is often a good choice. Is it imperfect and are there trade-offs involved? Of course, but there are with anything.

Even in hindsight I think Rails was a good choice for Airbnb. It got the company to where it needed to be. If they had chosen something else, there would have been different trade offs. The early team really benefited from the productivity benefits of Rails.

Source: I worked at Airbnb for five years and a very early team member told me this.

> Is it imperfect and are there trade-offs involved? Of course, but there are with anything.

No disagreement here. But the argument was made that Rails "scales pretty well" and I believe this is wrong — and I don't even mean in terms of performance (that probably too), but also in terms of architectural complexity. All these problems are solvable of course, but Rails makes it IMHO harder than some other technologies.

I haven't significantly worked with Rails since 2015, so I'm not up to speed with the current state of things, but in general I found that architecturally Rails can scale mostly okay, although it can be a bit tricky if you're not very familiar with the Rails internals, but it's not overly complex either in my experience. I was never a Rails super-expert either, and I managed to bolt on plenty of stuff for customers' specific needs, and the results worked fairly well and weren't too overly complex.

I don't doubt there are certain roadblocks though, and that some things fairly "simple" could be very hard and complex in Rails. I just never encountered them.

I've certainly seen a lot more overly complex crappy bespoke solutions when Rails + a few modifications would have been much better. This is like the old Greenspun's tenth rule: "any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp." – there are a lot of "ad hoc, informally-specified, bug-ridden, slow implementations of half of Ruby on Rails" out there.

Right now I mostly write web stuff with Go, which is the exact opposite of Ruby/Rails in almost every way. In spite of being so different, I'm fairly comfterable with both approaches, and I'm not entirely sure what I prefer yet (even though I've been doing this in Go for 6 years now); I certainly spent a lot more time on basic stuff that Rails just provides.

Rails is ultimately just a collection of libraries + some glue code, tooling etc., so you can, of course, build a well-architected Rails app with some discipline.

What I'm criticising is that a lot of the official guides (and/or DHH himself) often lead to problems down the road. For example, it is encouraged to do things through model callbacks. Except, once you have your send_email logic in a after_create callback and you figure out that you actually need to create users in different contexts too - e.g. in bulk updates if you need to import some data, where you don't want to always send an email - it will be painful to rewrite your code since you have no abstraction where that code should reside. Even DHH recognised this problem, when he pushed through ActiveRecord::Base.suppress [1] which was consided problematic by most everyone else (including the Rails core team). A better architecture would have a "service" or "concern" layer that would handle such things, but "the Rails way" doesn't advocate for anything outside of models, views and controllers. Though, to be fair, many real-world codebases do include such a service layer - but it's done differently everywhere.

There is also no abstraction for request validations. You're supposed to do all your validations in the model layer. But what if you have multiple requests mapping to the same model layer? Maybe the validations you want to run if an admin user updates a table are very distinct from the validations that should be run for a regular user. Again, while you can use ActiveModel objects for that, Rails doesn't particularly encourage this design and you can end up with a lot of coupling between your persistence layer and something which is essentially part of the business layer, and that can be hard to unentangle later.

Another famous problem IMHO is (by default) every single test loading the whole Rails context. This makes fast unit tests basically impossible and therefore TDD painful (which, IMHO, is particularly bad in a dynamically and heavily monkeypatched language - if you don't have static guarantees, you at least want to be able to test your changes quickly).

All of these are things that in other ecosystems - for example Spring - are handled much better. Now, I have criticisms about Spring too (slow boot times, excessive use of reflection, Hibernate is a mess, etc.) but at least it gives you some good tools to cleanly separate different layers of your application. For example, validation is generally done at DTO level, long before any of your data ever hits the database.

[1] https://medium.com/spritle-software/rails-5-activerecord-sup...