CQRS and REST API
REST, not CRUD
I always felt a smell with dogmatic REST API design, too often resulting in a cruddy CRUD interface.
This article, “REST API design, Resource Modelling” (REST-without-PUT) is four years old but more current than ever. It is absolutely brilliant, even though, IMO, a bit too long and dispersive, with the risk of missing the real key points.
I’m not repeating the content of the article I recommend to read (TL; Please Read), but I’m summarising few takeaways and thoughts.
My takeaways from the article
Unless your domain model is absolutely trivial, a purist REST approach based on 4/5 HTTP verbs falls short very quickly and pushes business logic (at least flow business logic) to the client.
Stay away from a CRUD approach. Do not update resources directly (with PUT). Model state changes in terms of Business Processes (e.g. “ChangeAddress”) as resources separate from those used to read the state of the domain (e.g. “Customer”… “Address”).
You POST a Business Process, possibly GET the state of the process from the same URI. But you GET the state of the affected resource(s) from separate URI(s). You never PUT direct changes to the resources.
This is basically a CQRS approach to REST API.
Separate resources represents Commands and Read Models.
Business Processes may execute asynchronously.
A Business Process resource can be read to retrieve the state of the process (running… successfully complete, partial or complete failures etc). This is an option. Your command may still execute synchronously returning the link of the updated resource(s) in its response.
As an implication of a CQRS approach, resources representing Commands (request for changes) and resources representing the state of the domain (Read Models) are decoupled.
No one-to-one relation between a Command resource and a Read Model resource. This makes easier to implement multiple representations of the same underlying domain entity as separate resources, as it should always be.
Note that Business Processes resources represent Commands, not Events. They may fail or be rejected. By definition, a Command may fail, while an Event (the consequence of a Command) never fails.
Also, this API design approach doesn’t imply using Event Sourcing, event though the underlying implementation might use Event Sourcing.
As a final note. Business Resources are actually Commands, so it is not a scandal expressing them as imperative sentences… with a verb! (…rumbles… thunders… the wrath of RESTful gods!).
“Nounified” resource names should be preferred, but don’t be dogmatic. Especially if the resulting name is weirds and cumbersome or, more importantly, if it doesn’t match any term actually used in the domain language.