This post is also available in Serbo-Croatian thanks to Jovana Milutinovich from

Lately I’ve been thinking a lot about the impact of the move to a thick client architecture for web applications, and I’m becoming more and more certain that this means that Rails-style MVC frameworks on the server-side are going to end up being phased out in favour of leaner and meaner frameworks that better address the new needs of thick-client architecture.

There are a few major reasons for this:

The server is no place for view logic

The devices available for running a web app are vastly different from when these web frameworks first sprung up.  The slide towards thicker / richer clients has been proceeding on pace with increases in processing power since the Web 2.0 days.  It’s much simpler to handle views and view logic in only one place, and that place is slowly moving away from the server side.  MVC has always been a strained pattern for a server-side, non-gui application and it is been a confusing and complicated trade-off to have the backend generating front-end logic.    Front-end frameworks like backbone.js, as well as advances in web technologies like HTML5′s history.pushState are now making server-free views a realistic quality of cutting-edge front-ends.   Rendering on the client-side also gives us the opportunity to create responsive designs based on device capability rather than having the server try to somehow figure out what the capabilities are without actually running on that device.

The kinks aren’t all the way out yet, but I do think the trend is clear.

Server-side Templating and .to_json are both underpowered and overpowered for the actual requirements of JSON APIs

There’s no need for templating on the serverside (or view helpers, or any view-related cruft) to generate simple JSON documents, but there are a tonne of problems left unsolved when we fail to see that generating a JSON API is more than just a serialization problem.

How should dates look?  (RFC3339 / ISO8601 of course!).  What should the JSON error document look like when you provide a 400 and want to tell the client why?  How should links to other resources in the API look?  How does a collection look?  How does pagination look?

These aren’t just serialization concerns, and they have nothing to do with templating.

HATEOAS is not just an academic pursuit

A thick client does not want to maintain a vast list of static strings representing all the crazy URLs that it will have to call in a non standard API.  As an API designer, you don’t want them doing this anyway, because hard-coded URLs and URL structures make it a real pain for you to change your API.

The AtomPub protocol, if you ignore its XMLiness,  gets this right — The thick client just knows the root URL (which serves up a simple service document) and is aware of a bunch of relationship types (the ‘rel’ attribute on ‘link’ and ‘a’ tags) that it can follow as necessary.  If a game client needs to access a list of players, it just goes to the root url, and follows the link with the rel property called ‘players’ (and probably remembers that link until the server says it has moved via 301 status code).  JSON has no concept of links or rel, but this is still easy to imagine and implement, and while it’s a teeny bit of extra work up front, the standardization buys you the ability to start writing smarter HTTP/REST clients for your frontend that take care of much more for you automatically, so you can spend time on real business logic and actually do something more productive than fiddle with the javascript version of a routes.rb file.

(A really great API framework might generate some or all of these links on its own and automatically put them in the JSON documents.  It’s pretty easy to imagine pagination links like next/back being generated automatically, or even links amoung resources in some cases, possibly based on some internally declared relationship.)

Rails-style MVC frameworks have a horrible routing solution for RESTFul JSON APIs

In a resource-oriented API, the router need not be concerned with the http methods that are or are not allowed for the resource.  That’s the concern of the resource and the resource alone.  When the router tries to manage that, you get the unnecessary verbosity of a route for every method supported by the resource, and you get the app incorrectly throwing 404s instead of 405s when a method is not supported.  This probably means that ‘controllers’ need to go away in favor of ‘resources’, and routes can be vastly simplified, if not completely derived/inferred by the framework.  Because we keep thinking in this conventional MVC style though, we miss the possibility and potential of vastly more simple applications that actually do a lot more more for us.

The Application Developer shouldn’t have to Deal with these Details

There’s no  reason for us to all separately think about these problems and solve them in a million different ways every time we’re confronted with them.  Aside from the years of wasted time this involves, we’ve also got a bunch of non-standard and sub-standard APIs to interact with, so all the client code needs to be custom as well and nothing is reusable.  This is why being RESTful is not just academic and this is why being concerned with the details is not pedantic.

As I said earlier, AtomPub gets a lot of this right.  A lighter-weight JSON equivalent would be a huge improvement to what people are doing today, because the conventions would mean that the framework can take care of most of these API details that we reimplement ad nauseum — or worse, not at all.  It also means that frontends can start to abstract away more of the HTTP details as well.  This is already starting to happen in the new frontend MVC frameworks but in almost every case, the HTTP end of things still needs to be handled in a custom way for every API endpoint.  There is still way too much work left to the application developer, and we’re silly to continue to do it over and over without coming up with a better abstraction.

CouchApps and WebMachine are just starting to touch on this style of architecture.  Backend-as-a-service platforms like Parse certainly understand how far this simple architecture can go, but ultimately there’s a huge need for a framework that can create more complex RESTful APIs (in a language that’s more general purpose and “blue collar” than Erlang).

Rails-style MVC frameworks are both too much, and not enough at the same time.  It really is time for a new framework to support this new architecture.

57 thoughts on “The Sun is Setting on Rails-style MVC Frameworks

  1. Pingback: The MVC Paradox – Bradley Holt

  2. We tried the approach you advocate for an app we built back in 2008 called Go. It was all RESTful APIs exposing JSON, and all the view logic was written in JavaScript. The problem was – it was a massive pain in the ass to write automated tests, and the tests we wrote were slow and brittle. Also it slowed down development because you had to change things at multiple layers in the stack, which makes it harder when you’re playing around with ideas during development. We actually moved _to_ Rails because it was easier to test and faster to code.

  3. @Jez: There are a couple of truths in what you’ve said that I can’t deny: (1) It’s a real pain to test highly interactive clients and (2) The separation of concerns slows you down at development-time. To (1), I agree it’d be best to avoid creating a highly interactive client if it’s not necessary to please your users (like Wikipedia). In those cases, it would be silly to recommend a thick client architecture. For applications where users are expecting much more than just the interactivity that comes with links and forms, I think the thick client architecture starts to make more sense. Testing tools are lacking for that style of architecture, but they’re improving at a really impressive rate. Now assuming that you are writing a highly-interactive application, I think that any speed you might get from not separating concerns properly (for my definition of ‘properly’ at least) is really just technical debt being added to a ball of mud. I especially don’t think pjax-style applications are easy to test or maintain, regardless of how fast they might be to write (PHP scripts with SQL next to HTML are fast to write as well). I also think that “API frameworks” and front end frameworks are very immature and as they improve will offset any development-time speed gains you might get from a more muddled architecture.

    BTW, your book is great. It’s a game-changer that everyone should read.

  4. Great arguments, I couldn’t agree more. As a Sencha Engineer, we often suggest our clients to provide a good JSON-API and ditch the “V” from their server-side frameworks. No need for template systems or view helpers, we have all of that on client-side JS frameworks.

    I’m curious to see alternatives though… You brought up the issue. Would be cool if we could reach some solutions. Would something like Sinatra simplify the Rails MVC making it more thin? What’s your take for alternatives?

  5. I use mvc and I think that having a good mix of both is important. I like the view based model but also love doing ajax json based data calls also. To me it all depends on the situation and the requirements.

  6. > you are saying the new trend is single page apps that uses a RESTful API

    sums it up nicely.

    I did this 5 years ago to survive a j2ee portal project where the server-side programming model was hopelessly brittle and all our development systems were too underpowered to run the dev environment, not to mention our brains…

    SPADE existed in 2006, Trimpath. Still in production.

    Nevertheless, if your server-side model isn’t hopelessly busted, then don’t necessarily do SPADE.. Drupal and AribaWeb come to mind as tested server-side models which are still sort of interesting. But they’re not ready for mobile really.. are they? Then again google probably wouldn’t want pages to go away…

Leave a reply


<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>