I think that RPC protocols and REST protocols live on very different abstraction levels and should not be compared like alternatives. This is maybe the main problem I have with the current wave of REST criticism. If we just accept that no one will be happy to force an RPC kind of API through REST, a domain specific API that was made for resource synchronization, the discussion could be more productive.
As programming languages use functions and RPC is a way to use those through a network of some kind, of course RPC APIs are the most generic and transparent way to achieve this. We now have amazing technology like gRPC, websockets, Cap’nProto, ProtocolBuffers, MessagePack and similar for this and HTTP is maybe a good fallback transport layer for legacy support but in principle these don’t need anything from the HTTP layer but are far better to be put through pure websockets or pure UDP/TCP.
Best is to look at two extremes and then at how real world mixed use cases can be modeled best:
- Pure RPC APIs:
everything that fits to things like message passing, very dynamic and multi dimensional queries, requesting view models, triggering events, remote algorithm execution, sending mutations. These things are just best implemented using the RPC technology I mention above. These concepts are often not even connected to the concept of a ‘Resource’, so it will run into all the REST problems we read about.
- Pure Resource APIs:
Any protocol that should synchronize or publish consistent state and state changes on resources and needs access to the full resource for consistency while abstracting implementation details as much as possible, is best modeled in REST. Pay attention to how relatively narrow this application is compared to the description above. Still, this applies to A LOT of systems, as long as the concept of a resource makes sense in the logic of that system:
For the logic of REST I find the following definition most practical: A resource is an entity that makes sense to be theoretically exposed as a unix file and whose state at a certain time makes sense to be validated by a simple hash function. This analogy is also interesting because it mirrors the development of plan9 (everything is really a file/everything should have a REST interface) being transformed into a more real world linux world (there are many file like APIs, but also d-bus etc. / there will be many REST APIs where it makes sense but also many RPC protocols)
Notice how every REST API can relatively easily be modelled in a RPC style API (though probably reinventing the weel) but not the other way around.
There are also two important technologies to have in mind when thinking about the real application of REST APIs, even if you use completely different technology in reality, but the purity of those technology implementations and the fact there are real Resources to check your thoughts against is an extreme help:
couchDB and webDAV
— does this api make in theory sense to be exposed as a webDAV server? How ridiculous would this api look when mounted in the file explorer? The more ridiculous the interaction with this API would be the less likely REST is a good model for your api. The more nerdy/nice use cases you find that would make such an interface awesome, the better it is suited for REST.
— if you know couchDB better than webDAV this works the same, how much would it make sense to model this API as a couchdb database with documents and revisions for versions of documents?
Real world APIs have mostly always both aspects. The key is finding the natural main idea of the API and indentifying and solving the other side of the coin as edge cases.
- If your API is mainly RPC style but you have a stronger need to act on resources, this is where graphQL comes in, this is also why I think graphQL makes most sense via web socket and I don’t think of it as an alternative to REST but as a tool belt to empower RPC APIs with stronger data needs.
- If your API is huge and can be split into domains that fit best to both worlds it makes sometimes sense to have two cleanly modeled separate APIs. This seems strange at first but this is exactly what happens if Web apps have a REST API but also use websockets for certain features.
- If your API is mainly a perfect REST fit but has some RPC aspects then of course its still OK to model RPCs as REST but be clear what those endpoints are and be ready to replace them if you run into the known problems, just knowing consciously about this already helps a lot.