LOCAL STATE IS A CLOUD ANTI-PATTERN

Two of the core promises of cloud is offering elasticity and availability. Elasticity is the ability to grow or shrink infrastructure as the demand for your service changes. Availability on the other hand, is the ability to sustain a failure of e.g an availability zone (AZ) or a region without impacting user experience. AZs on the AWS cloud are in fact the unit of availability and most of our manages services like S3, Kinesis, DynamoDB or Lambda take full advantage of this, transparently for the customer. If you aim at being Well-Architected, your services should be deployed across several AZs.

Everything fails, all the time! Werner Vogels

Having an elastic and available application work across several AZs comes with one fundamental consequence: it should be able to scale up-down in any AZs (or Region for the extreme) at any time. When you scale up, for example, a Load Balancer often registers that information in its routing table and will start sending traffic to that new instance, container or function. And to do so without failure, your code cannot make assumptions about local state.

If you had user specific local state running in your application, well, it’s gone — and if that local state was the content of a shopping cart or a login session, you will make your customer really unhappy since that data won’t propagate to other instances and that user session will be lost.

Luckily the solution is simple: sharing state with any instances, containers or functions by using in-memory object caching systems like Memcached or Redis depending on the structure of your object and your requirements in terms of performances (In some case, you can use databases like DynamoDB coupled with DAX).

Doing so, any new instance of the backend application starting will be able to get the previous state of the application from the cache and get on with the tasks at hands (again think shopping cart).

** Unless you use session stickiness (Note: please don’t use session stickiness for everything, that’s another cloud anti-pattern)

Local-state is the reason fork-and-lift migrations to the cloud are often sub-optimal or simple failure. Many of the “old” applications that use to run on-prem, in one datacenter won’t get the full cloud benefits offered by elasticity and availability unless they are state-free.

So my advice, if you need to fork-and-lift, fine, you already get some benefits by simply moving to the cloud, but your task number one is taking care of the state — only then you will unleash the full power of the cloud.



About transient state:

First, let’s define what is transient state: From wikipedia, a system is said to be in a transient state when a process variable or variables have been changed and the system has not yet reached a steady state.



Many applications use transient state to operate: think counters, job progress states, lists, sets or any data that, even if useful now, is irrelevant, depreciated or simply mutated shortly after. I have worked on many applications or systems that store that transient state in the databases (most of the time SQL) which is suppose to be a persistent storage. Well, every single time that system had to scale up, those database requests to write, update (often locking) or delete that transient state in the database took the application down; the number of database queries waiting to be executed grew larger proportionally to the number of users, and eventually took the application down.

Do not store transient state in (SQL) databases, use specialised datastore for that. Got some lists, sets, sorted sets, hashes or keys that store transient state? use Redis (for example) since it was built for that very purpose.



If you are going to store something in your (SQL) database, make sure it is data that won’t be mutated shortly after, otherwise, it is a waste of database scalability credits.

Redis is just one example. DynamoDB, Memcached or Elasticsearch for example, are great tools that can help take the load off your SQL databases, especially when you start scaling.