Can We Make REST API Transactional Across Multiple Calls?
I got interesting feedback from one of my readers after publishing my REST API Is Not Transactional blog post:
One would think a transactional REST interface wouldn’t be too difficult to implement. Using HTTP1/1, it is possible to multiplex several REST calls into one connection to a specific server. The first call then is a request for start a transaction, returning a transaction ID, to be used in subsequent calls. Since we’re not primarily interested in the massive scalability of stateless REST calls, all the REST calls will be handled by the same frontend. Obviously the last call would be a commit.
I wouldn’t count on HTTP pipelining to keep all requests in one HTTP session (mixing too many layers in a stack never ends well) but we wouldn’t need it anyway the moment we’d have a transaction ID which would be identical to session ID (or session cookie) traditional web apps use.
However, the real problem lies in the way REST API servers are usually implemented.
Let’s evict the obvious elephant from the room before you rush to point out that every single REST API call is transactional. I hope that’s true, but I don’t care about that. What I’d like to have is:
- The ability to roll back five independent changes to the system if one of my changes fails;
- Ideally the ability to make changes that are not visible to the outside world until the commit REST API call.
Implementing such a system is trivial if the REST API calls do nothing more than modify the data model which is then instantiated once we execute the commit call.
Unfortunately most systems (or network devices) don’t work that way because it’s much simpler to execute a function call within the system and modify system state the moment a REST API call is received or a command is typed in the CLI.
Even worse, the execute-changes-immediately paradigm is so widely accepted that it’s totally unrealistic to expect that we’ll get transactional configuration consistency we have with Junos, IOS-XR or Arista EOS in SDN controllers, orchestration systems or intent-based products (isn’t it great to have three marketing names for the same stuff?) with rare exceptions like Cisco APIC.
Like they say, sometimes you’re too busy to yammer to realize what you had until you lose it… Welcome to the brave new RESTful world.
The problem you described here has been solved many years ago with maintaining sessions state (cookies, sessions tokens, transaction ids etc). If any particular implementation of API interface lacks that, it's not a problem of REST API as a whole.
On the other hand, can you imagine you make 5 independent changes in the DB, or 10 changes in your aws (or whatever else) environment without influencing the system state. No, it doesn't work this way.
So splitting your network changes in multiple parts, applying them, checking system state after each step can also this "problem" of non-transational REST
You might also want to read https://en.wikipedia.org/wiki/Representational_state_transfer, in particular the "statelessness" part.
Finally, compare what you have to do to recover from a failed configuration of a network device with "commit" capabilities with what you have to do if you're using REST API.
I wrote about that in https://blog.ipspace.net/2019/04/rest-api-is-not-transactional.html and https://blog.ipspace.net/2018/09/infrastructure-as-code-netconf-and-rest.html... but the of course it's much faster to write a comment saying "this problem has been solved, what are you complaining about?"
REST is stateless by definition (not putting wikipedia links here ;)
The problem you describe is solved by applications you write (think Cloudformation as an example), which leverage REST API, it is nothing to do with REST API itself. It can be a long discussion though...
BTW, the subliminal message of this series of blog posts was "we had something like CloudFormation forever... why are some people so keen to see it replaced by REST API" ;)