RESTful thinking considered harmful

It has been interesting and at times amusing to watch the last couple of intense debates in the Rails community. Of particular interest to me are the two topics that relate to RESTful design that ended up on the Rails blog itself: using the PATCH HTTP method for updates and protecting attribute mass-assignment in the controller vs. in the model.


These discussions are interesting because they are both about the update part of the CRUD model. PATCH deals with updates directly, and most problems with mass-assignment occur with updates, not with creation of resources.

In the Rails world, RESTful design and the CRUD interface are closely intertwined: the best illustration for this is that the resource generator generates a controller with all the CRUD actions in place (read is renamed to show, and delete is renamed to destroy). Also, there is the DHH RailsConf '06 keynote linking CRUD to RESTful design.

Why do we link those two concepts? Certainly not because this link was included in the original Roy Fielding dissertation on the RESTful paradigm. It is probably related to the fact that the CRUD actions match so nicely on the SQL statements in relational databases that most web applications are built on (SELECT, INSERT, UPDATE and DELETE) on the one hand, and on the HTTP methods that are used to access the web application on the other hand. So CRUD seems a logical link between the two.

But do the CRUD actions match nicely on the HTTP methods? DELETE is obvious, and the link between GET and read is also straightforward. Linking POST and create already takes a bit more imagination, but the link between PUT and update is not that clear at all. This is why PATCH was added to the HTTP spec and where the whole PUT/PATCH debate came from.

Updates are not created equal

In the relational world of the database, UPDATE is just an operator that is part of set theory. In the world of publishing hypermedia resources that is HTTP, PUT is just a way to replace a resource on a given URL; PATCH was added later to patch up an existing resource in an application-specific way.

But was it an update in the web application world? It turns out that it is not so clear cut. Most web application are built to support processes: it is an OLTP system. A clear example of an OLTP system supporting a process is an ecommerce application. In an OLTP system, there is two kinds of data: master data of the objects that play a role within the context of your application (e.g. customer and product) and process-describing data, the raison d'être of your application (e.g., an order in the ecommerce example).

For master data, the semantics of an update are clear: the customer has a new address, or a products description gets rewritten [1]. For process-related data it is not so clear cut: the process isn't so much updated, the state of the process is changed due to an event: a transaction. An example would be the customer paying the order.

In this case, a database UPDATE is used to make the data reflect the new reality due to this transaction. The usage of an UPDATE statement actually is an implementation detail, and you can easily do that otherwise. For instance, the event of paying for an order could just as well be stored as a new record INSERTed into the order_payments table. Even better would be to implement the process as a state machine, two concepts that are closely linked, and to store the transactions so you can later analyze the process.

Transactional design in a RESTful world

RESTful thinking for processes therefore causes more harm than it does good. The RESTful thinker may design both the payment of an order and the shipping of an order both as updates, using the HTTP PATCH method:

    PATCH /orders/42 # with { order: { paid: true  } }
    PATCH /orders/42 # with { order: { shipped: true } }

Isn't that a nice DRY design? Only one controller action is needed, just one code path to handle both cases!

But should your application in the first place be true to RESTful design principles, or true to the principles of the process it supports? I think the latter, so giving the different transactions different URIs is better:

    POST /orders/42/pay
    POST /orders/42/ship

This is not only clearer, it also allows you to authorize and validate those transactions separately. Both transactions affect the data differently, and potentially the person that is allowed to administer the payment of the order may not be the same as the person shipping it.

Some notes on implementation and security

When implementing a process, every possible transaction should have a corresponding method in the process model. This method can specify exactly what data is going to be updated, and can easily make sure that no other will be updated unintentionally.

In turn, the controller should call this method on the model. Using update_attributes from your controller directly should be avoided: it is too easy to forget appropriate protection for mass-assignment, especially if multiple transactions in the process update different fields of the model. This also sheds some light in the protecting from mass-assignment debate: protection is not so much part of the controller or the model, but should be part of the transaction.

Again, using a state machine to model the process makes following this following these principles almost a given, making your code more secure and bug free.

Improving Rails

Finally, can we improve Rails to reflect these ideas and make it more secure? Here are my proposals:

  • Do not generate an update action that relies on calling update_attributes when running the resource generator. This way it won't be there if it doesn't need to be reducing the possibility of a security problem.
  • Ship with a state machine implementation by default, and a generator for a state machine-backed process model. Be opinionated!

These changes would point Rails developers into the right direction when designing their application, resulting in better, more secure applications.

[1] You may even want to model changes to master data as transactions, to make your system fully auditable and to make it easy to return to a previous value, e.g. to roll back a malicious update to the ssh_key field in the users table.

A big thanks to Camilo Lopez, Jesse Storimer, John Duff and Aaron Olson for reading and commenting on drafts of this article.

Update: apparently many people missed to point I was trying to make. Please read the followup post in which I try to clarify my point.


  • Nick Drew
    Nick Drew
    March 30 2012, 09:44AM

    Major Sub-Editor failure: Roy Fielding, not Robert Fleming

  • Roland
    March 30 2012, 09:48AM

    I don’t see how having different URLs is “non-restful”. i.e. you could have:

    POST /orders/42/payment
    POST /orders/42/delivery

    or similar. It doesn’t matter if these “creates” actually end up doing an update in the model.

  • @Shopify Willem van Bergen
    Willem van Bergen
    March 30 2012, 09:51AM

    Nick: thanks, fixed.

  • @Shopify Willem van Bergen
    Willem van Bergen
    March 30 2012, 10:02AM

    Roland: I agree. My main issue is that REST actions and CRUD database actions are considered equivalent in Rails, so it pushes people not to to think about breaking this link if it makes sense.

    Design thinking should start from the process you are supporting, and only then could be wrapped in a RESTful design if you want, not the other way around.

  • Kristoffer Garcia
    Kristoffer Garcia
    March 30 2012, 10:55AM

    Actually, exposing a state machine through hypermedia so that the client may initiate state transitions is a core concept of REST as described by Fielding. It’s really right there in the title “Representational State Transfer”.

    Now, the topic of hypermedia and state transfers is a deep one, which is probably why everyone glosses over it and latches on to URI design part.

    Nevertheless, regarding the URIs you present as examples, I would say the following…

    POST /orders/42/pay
    POST /orders/42/ship

    Are actually better examples of RESTful URIs that represent state than the following…

    PATCH /orders/42 # with { order: { paid: true } }
    PATCH /orders/42 # with { order: { shipped: true } }

    I love Rails and the Rails community, but perhaps the views in the community regarding REST are oversimplified. Never mind what DHH said or one may think he said. The primary HTTP operations may sound similar to CRUD but they are operating on a different layer with a different kind of thing. I find it helpful to look at it in the following manner. Resources are intended to represent state, not Relations. A Resource will rarely map directly to a Relation and an operation on a Resource will rarely map directly to a like operation on a Relation (this only happens in simple applications which unfortunately is what most examples on the topic show). Posting an Order could translate to an update to a Customer relation, a creation of a Order relation, a creation of a ShippingAddress relation, etc. If the customer wanted to change their address, that would probably be accomplished through posting a ShippingAddressChange resource which could translate to an update to the existing ShippingAddress relation to disposition it (take away it’s position as the primary/active shipping address) and then create a new ShippingAddress relation, etc.

  • Kiall Mac Innes
    Kiall Mac Innes
    March 30 2012, 11:05AM

    The URLs described, to me, are not RESTful at all.

    POST /orders/42/pay
    POST /orders/42/ship

    These are not truly RESTful..

    The RESTful solution is:

    POST /transactions # with {order: 42, type: payment, amount: $100}
    POST /dispatch # with {order: 42}

  • Rick
    March 30 2012, 11:12AM

    Building on what Kristoffer said, including these Hypermedia links in your representations can be very powerful. When an Order is created, it’s in a pending state that still needs payment and to be shipped.

    { “id”: 42
    , “_links”:
    { “self”: { “href”: “/orders/42” }
    , “pay”: { “href”: “/orders/42/pay”, “method”: “post” }

    POST /orders/42/pay

    { “id”: 42
    , “paid”: true
    , “_links”:
    { “self”: { “href”: “/orders/42” }
    , “ship”: { “href”: “/orders/42/ship”, “method”: “post” }

    POST /orders/42/ship

    { “id”: 42
    , “paid”: true
    , “_links”:
    { “self”: { “href”: “/orders/42” }

    The hypermedia links can let the client know what next operations are available.

    The Rails REST conventions are designed for CRUD. The PATCH method would be suitable for updating the title of a Blog Post, not something as complex as shipping an order. You’re definitely right to question the conventions and go with what works best for your application though.

  • Rick
    March 30 2012, 11:13AM

    You could also expose payments and shipments as resources too:

    POST /orders/42/payments

    Location: /payments/42
  • broken
    March 30 2012, 11:29AM

    Most “RESTful” APIs aren’t.

    For example REST is not supposed to have documented URLs.

    If client knows how to build a URL, it’s not REST.

  • Brian
    March 30 2012, 12:02PM

    @Rick – you may have already addressed this question in your last comment, but I’d like to open it up a bit.

    First, I really appreciated this article. Its critical for developers to understand the layers of abstraction involved in building apps – especially when it comes to intermingling language between business entities and network transport layers.

    Second, my question: in the process scenario, how does one indicate the flow through the process. One cannot POST directly to /orders/42/ship before hitting /orders/42/pay. Is there a way to represent the process chain itself through REST? @Rick, I think you may be on to something with specifying “links”.

  • Rick
    March 30 2012, 12:52PM

    Hypermedia is a core component with REST. Getting a resource should give you the next actions, so you (well, your client) doesn’t have to guess or build URLs. Getting an Order that hasn’t been paid for returns the “pay” URL. Once it’s paid, then it returns the “ship” URL. Accessing either of the ship or pay URLs could return the updated Order resource, letting the client know what next actions are available.

    This requires smarter clients of course. Most OSS API clients are just wrappers around HTTP calls, which doesn’t even come close.

    As I’m saying this, you could of course fire back that the GitHub API that I work on doesn’t do any of this. I also try not to claim it as a “REST API” :) I’ve been looking at how to integrate proper Hypermedia links in an existing API. The most promising solution for JSON I’ve seen is HAL:

    If you’re still interested, I’d highly recommend checking out Jon Moore’s talk on Hypermedia APIs:

  • Kevin Ball
    Kevin Ball
    March 30 2012, 01:31PM

    I’ve thought for a while that REST was often more appropriate for APIs than for consumer-facing web applications. The REST approach makes great sense for the way a software developer wants to think about interacting with an object… but often does not well match the way that we want to design our UI.

    I tend to think the structure of the controller should be designed to match the processes it is supporting, not the other way around…
  • Brian
    March 30 2012, 01:54PM

    @Rick: thanks for the thoughts and links. Off to do some reading!

  • Nick Bauman
    Nick Bauman
    March 30 2012, 02:03PM

    Rick’s comment is spot on. Willem’s approach is not ReSTful, which isn’t bad per se.

  • PJ
    March 30 2012, 02:52PM

    How about you keep it RESTful and change

    POST /orders/42/pay
    POST /orders/42/ship


    POST /orders/42/paid DATA: value=true
    POST /orders/42/shipped DATA: value=true

    ? This will let you have your separate protection and still be the RESTful exposure of sub-resources of an individual order. Though I don’t think it’s RESTs issue that your framework doesn’t make it easy to implement per-attribute protections of resources.

    The issue is, however, what if you want to make both of those changes in the same transaction ? Or better yet, what if you have dependent attributes, like, say, a tracking number.Then you want to do:

    POST /orders/42 DATA: shipped=true ; trackingno=1234

    And we ship everything with tracking numbers, so it’s invalid to do it as two transactions:

    POST /orders/42/shipped DATA: value=true
    => 400 Bad Request; no tracking number specified
    POST /orders/42/trackingno DATA: value=1234
    => 400 Bad Request; that order hasn’t shipped yet

    Part of REST is that by exposing the resources, they give control to the user to decide how much and what they want to change at once, while still being able to enforce constraints.

  • Jamieson Becker
    Jamieson Becker
    March 30 2012, 04:36PM

    Excellent article!

    This is indeed RESTful, although I agree that it’s not too great.
    PATCH /orders/42 # with { order: { paid: true } }
    PATCH /orders/42 # with { order: { shipped: true

    “Isn’t that a nice DRY design? Only one controller action is needed, just one code path to handle both cases!”

    In my view, implementation details (or pain!) don’t matter wrt correctness. However, I agree with your latter choice, but for different reasons. In my view, PATCH actually results in rather fragile code. (As a side note, all parts of a resource should be treated discretely with regards to permissions: you should be doing permission checks on the whole resource, not part of it, so if Joe can change one part of a resource but not another, then that resource needs to be split into two resources. For the same reasons, PATCH is basically too fragile; break your model into more discrete chunks.)

    This is the only problem I have with your entry (which is GREAT! except for the headline ;)) … The following is definitely REST, too.

    POST /orders/42/pay POST /orders/42/ship In fact, I’d argue it’s more restful. It’s clean, it’s breaking into multiple resources, and it’s using a resource to represent the state transition.

    As a side note, this should be a PUT, not a POST, since you’re not specifying an ID for the paid resource and there can only be one instance of that resource (ie /orders/42/pay) It’s now idempotent, too.

    I wrote a blog entry about PUT vs POST a few years ago. They can both be used to CREATE something. I think the Rails community (and probably most RESTful frameworks) tend to separate PUT vs POST in un-speclike ways or try to match them up to implementation or SQL details; sometimes those abstractions break down, as you point out!

  • Johnathan
    March 30 2012, 05:08PM

    Can you please change the article title to something other than “considered harmful” already? It actually does a dis-service to your credibility and the rest of your opinions about the topic. Why not let people come to their own conclusion about what is and is not “harmful thinking” based on the arguments and discussion presented?

  • Erik Ashcraft
    Erik Ashcraft
    March 31 2012, 11:25AM

    At a certain point, I think you stray from being a RESTful service. In my opinion your examples break the layered system constraint of a RESTful system.

    These are remote procedure calls.

    POST /orders/42/pay
    POST /orders/42/ship

  • Jamieson Becker
    Jamieson Becker
    March 31 2012, 01:54PM

    @Erik point well taken, but the remote procedure is POST in that example, not /orders/42/pay. To your point, /orders/42/payment is probably a better resource name.

    This was a great article and thanks to Willem for hitting something that most people barely understand (or care about) and pointing out how important it really is!!

  • Darrel Miller
    Darrel Miller
    March 31 2012, 05:22PM

    Unfortunately this article should be titled “The Rails perception of REST considered harmful”

    There are a growing number of people like Rick who are starting to understand that REST has nothing to do with what a URI looks like.

    If you are really interested in learning more about what Fielding meant by REST, rather than the buzz word, come join us at the RESTFest unconference in September (

  • hmm
    March 31 2012, 07:41PM

    Personally it seems like instead of:

    POST /orders/42/pay

    I would prefer not to use OrdersController at all and instead do:

    POST /orders/32/payments

    To create a new payment using PaymentsController nested routes. And similarly:

    POST /orders/69/shipments

    Is `create` on ShipmentsController nested routes.

    There was an article or rails guide on the subject that basically said if you find yourself writing ‘member’ or ‘collection’ in routes.rb that you should consider if you are actually dealing with a new resource… And I think that’s the right way to think about it.

  • RoboHead
    April 04 2012, 01:46AM

    Why not use parameters for passing order number? Does it differ from REST architectural style if you use parameters?

    I am thinking of

    POST /MarkOrderPaid?orderNum=42
    POST /MarkOrderShipped?orderNum=69

  • David Woodfin
    David Woodfin
    April 09 2012, 03:07AM

    Thank you for your nice information.

  • David Woodfin
    David Woodfin
    April 30 2012, 01:00PM


    Thanks for your comment. I’m glad you find this collection useful.


  • sevvy
    May 15 2012, 03:05AM

    Do you plan on moving to Canada in cheap rate? Then for more details contact with us.
    Have a nice day………..

Leave a comment ...

Start your free 14-day trial of Shopify