REST is not CRUD, and here’s why.

I have encountered several web articles recently which attempt to describe REST verbs (“get”, “put”, “post”, “delete”) in terms of traditional database CRUD (“create”, “read”, “update”, “delete”) operations, and then get stuck trying to map one set to the other.

On the one hand, it’s easy to see why the confusion happens. Both sets have four basic operations, and both sets are concerned with manipulation of stored resources, both have an operation called “delete”, and “read” sounds pretty much like “get”. However, that’s where the similarity stops.

For some recent examples of confusing REST and CRUD, see:

REST and usablity shouldn’t be mixed

Two stage resource oriented web application architectures

Hazem Ahmed Saleh: The rules behind designing a good RESTful service

Even the, otherwise very good, REST Dialogues sometimes fall into this trap.

So, what is the difference?

“Get” and “read” are essentially the same, at least when it comes to fetching raw resource data.

There is a difference in usage, though. In REST a “get” fetches a single resource. CRUD, on the other hand, is often associated with relational databases, which excel in returning sets of results. The common REST approach to multiple results is to return a resource which includes URIs for each resource in the collection (perhaps also with some summary information); the REST client is then free to individually “get” any or all referenced resources which it requires, or if necessary to instead fetch them from a local cache. As an example, consider the loading of images in a web page.

“Delete”, although similar on the surface has some important differences underneath.

In CRUD, the relational heritage often implies the ability to do complex deletes, such as deleting all resources which meet some criteria. In REST the “delete” operation is a simple delete of the resource at a single URI. To delete multiple items using REST typically requires multiple, separate, “delete” requests.

“Put” and “update” can be similar or different depending on interpretation.

The REST “put” operation has strict and well-defined semantics. It ensures that the specified URI has the supplied resource. If the URI is invalid it fails; if the URI contains no resource the supplied resource is placed there; if the URI contains a different resource it is replaced with the supplied resource; if the URI contains the same resource there is no apparent change to the resource at the URI. The CRUD “update” operation, on the other hand is less well-defined. SQL standards do not include a “replace”, “put”, or “insert or update if exists” operation (although many vendor implementations implement such features in a non-standard way). With this in mind, some people interpret the CRUD “update” operation as equivalent to an SQL “update” statement (which only applies if the resource already exists), while others treat it more generally as any form of change which is not a “delete”.

This only leaves “post” and “create”. These are the most different of all.

In REST, “post” is used for any action which results in a resource change or side-effect, and cannot be repeated without the change or side-effect happening again. An SQL “insert” operation would be implemented as a REST “post”, for example, but so would an SQL “update” which increments a value, or the sending of an email. A practical rule of thumb is that a “post” should be simple and quick, leaving the way for future changes using “put” as soon as possible. A CRUD “create” is a quite different thing. “Create” explicitly creates a new resource, and is undefined if that resource already exists.

REST has no direct analogue of “create”. If it is needed (for example) to create and populate a new resource, it is typical to call “post” on some parent resource which results in the return of, or redirect to, a new (empty) URI, and then populate the URI with one or more “put” operations. This approach has the big advantage that the impact of an accidental re-“post” is minimised. In a well designed system, the creating of a new URI could be as low-impact as incrementing an integer, only requiring storage of resource data if/when it is later populated using “put”.

CRUD, on the other hand, has no direct analogue of “post”. A CRUD “create” will probably have side effects, as will some CRUD “update” operations. CRUD is also limited in that it does not include the concept of side-effects outside the resources being managed. There is no way to describe sending an email in terms of CRUD, for example.

In summary, the REST and CRUD are different in many ways, some subtle and some less so.

REST is an approach designed to enable scalable distributed applications to clearly distinguish actions which make no change and thus may be cached or repeated (“get”) from those which make a change but may be casually repeated without problems (“put”, “delete”) from those which should neither be repeated nor cached (“post”). This in turn enables intermediate software (be it in the form of libraries, reusable components, or entirely separate systems) to implement sensible optimisation and error-handling strategies without needing knowledge of the content or relationships of the resources.

CRUD is a description of some generic operations on stored data, with no particular intention of serving as a distribution protocol, and thus little or no planning for the mitigation of problems such as accidental duplicates, time-outs or lost requests.

Attempts, however well-intentioned, to explain one by analogy with the other run a great risk of increasing confusion rather than clearing it. If you are considering using such an analogy, please think twice.


  1. Or maybe it can help to make the analogy. Doing composite operations, as you discussed, is one example. Quick REST APIs might require one-off hits for each resource, but could the URI itself describe a composite resource? Really, resources are more often virtual than being simple standalone files or documents. Thinking about, say, the relationship of SQL (from a CRUD view) and REST is helpful, and I think you’ve contributed to that here. I also agree that differences are worth highlighting.

  2. Thanks for the comment, Tom. For me the point about the fetching of single resources vs the fetching of multiple resources is one of different approaches to optimisation.

    The usual approach with databases (and thus with common understanding of CRUD) is that all data may vary, and thus all data should be fetched each time. If this assumption holds, then aggregating a group of resources into one fetch makes a lot of sense, as it cuts down on the overhead of establishing and managing multiple connections for multiple requests.

    With REST, on the other hand, the assumption is that all “get” requests may be cached. In particular, the REST clilent may already have fetched and cached some or all of the resources already. If this assumption holds, then returning a set of resource URIs and allowing the client to fetch only those which it has not already got makes a lot of sense.

    Let’s consider my example of images in a web page.

    The approach of returning everything every time in one request would typically result in huge and heavy web pages, each containing all the referenced images, videos, sounds, flash animations and so on. Typically the size of even one image dwarfs the few hundred (or at most few thousand) characters of the page HTML.

    On the other hand, the approach of including only the URIs of the images, videos, sounds, flash animations etc. allows the client (in this case a web browser) to choose what it does. It may choose to cache images etc.; it may choose to ignore them. It may choose to fetch them all every time.

    I hope we all agree that the overall web browsing experience is much smoother when a browser has already cached all the images etc, used in a page, and the same can also be true in distributed systems.

    As another example, consider a search service. Such a service could return the full data of all matching resources every time, or it could return just the URIs of matching resources and allow the search client to use cached versions where possible. In common scenarios, the most popular search results will be returned lots of times, and thus can be cached, allowing the responsiveness of the system will improve over time. If all resources are returned every time, then the responsiveness can probably never improve without hardware changes.

    Does that make sense?

  3. Pingback: Confluence: Developer Advocate

Comments are closed.