In this blog post, we will take a slight detour from Cloudstate and understand why we need to give a second thought to the way CRUD operations are done in Serverless Computing.
Before diving deep into the need of reconsidering CRUD operations strategy in Serverless Computing, let’s first understand CRUD.
What is CRUD?
CRUD is an acronym for the four general operations that a database performs, i.e., Create, Read, Update, and Delete. Every web application uses CRUD operations of a database for storing/retrieving data.
However, accessing the database or doing CRUD operations in a serverless computing world is totally different. Because every User-Function that needs to R/W data would need access to the database.
Now this leaves unrestricted access to the DB with the User-Function. This means that the User-Function has to manage all the nuts & bolts of the data access & storage. Also by doing this, you are handing over the responsibility of moving all the operational concerns of the database from the Serverless framework to the User-Function.
The issues that this strategy might create are as follows:
- Is the operation a read operation, or a write operation?
- Can the data be cached?
- Do we need to follow strong consistency or not?
- What to do in case of a transaction’s partial failure?
Adding State = More Trouble
From our previous blog post, Cloudstate (Part 2): Why we need it? we came to know that one of the primary advantages of using Cloudstate is maintaining the State in a reactive way in Serverless Applications.
Now, when we try to use the existing CRUD strategy, i.e., providing unrestricted access to the User-Function for the whole database, then it won’t work. Why?
Because we can’t give access to the whole State to a User-Function as that would require us to pass the whole State to the User-Function and send the whole updated State from the User-Function.
So what’s the solution to this problem?
Restricted I/O Patterns
A probable solution to this problem is the use of data storage/access patterns which will restrict the Input/Output of data. For example, Key-Value, Event Sourcing, and CRDTs. Let us see what they are.
Event Sourcing ensures that not just the State is updated when a request (command) arrives in, but also the Event is stored which made that change to the State. In Event Sourcing, the State In is the Event Log while State Out is the updated Event Log which is generated as a result of handling a Command.
This pattern ensures that the User-Function updates the State without accessing it directly. And it removes the need to provide direct access to the State to the User-Function.
A Conflict-free Replicated Data Type (CRDT) is a data structure that is replicated across multiple machines, where the replicas can be updated independently and concurrently when any one of the (many) replicas is updated. In it, State In is a stream of Changes to the State, and State Out is also a stream of Changes to the State.
The advantage of this pattern is the same as of Event Sourcing, i.e., no direct access to the State. As it just needs the Changes done to the State so that it can update the State with the help of them.
This is the least complex and most used pattern. As in it, the Key is the State Out and the Value is the State In.
In terms of advantage, this pattern is slightly different than the above-mentioned patterns as it accesses the State directly, but not the whole State. Instead, it accesses the State modified by the just previous User-Function.
Hence, when you are thinking about using CRUD operations to your Stateful Serverless application, then give a second thought to the CRUD strategy to use. So that you can keep it reliable and consistent.
In the upcoming blogs we will explore more about Cloudstate, hence stay tuned 🙂