REST is not CRUD, and here’s why.
31-Oct-08
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.