Skip to content
lorebow

Processes

Run the app as stateless processes that share nothing, and keep anything that must last in a backing service.

KFounder and editor 176 words 1 min read Find it on the map
On this page

Execute the app as one or more stateless processes. A process may use its memory and disk while handling one request, but must never count on finding anything there later. The next request may go to a different process, and this one may be restarted at any moment.

Anything that has to last, like users, carts, counters and sessions, belongs in a backing service.

#What goes wrong with state in memory

A visit counter, kept in a global variable:

app.pypython
from flask import Flask
 
app = Flask(__name__)
visits = 0  # lives in this process's memory only
 
@app.get("/")
def index():
    global visits
    visits += 1
    return f"Visits: {visits}"

With one process, it works. Run two behind a load balancer, and each keeps its own count:

Two processes, two different answersVisits: 1Step 1 of 4
BrowserrefreshingLoad balancerweb.1own counterweb.2own counterRedisshared counter

1.First request

The load balancer sends it to web.1, which counts 1.

app.pypython
import os
import redis
from flask import Flask
 
app = Flask(__name__)
store = redis.Redis.from_url(os.environ["REDIS_URL"])
 
@app.get("/")
def index():
    return f"Visits: {store.incr('visits')}"

INCR is atomic, so two processes adding at the same moment never lose a visit.

#Sessions and sticky sessions

Logged-in sessions are state too. Store them in Redis or a database, or in a signed cookie, so any process can read them.

Sticky sessions, where the load balancer always sends a user to the same process, hide the problem instead of fixing it: the session still disappears when that process restarts. The twelve-factor rule is to never depend on them.

Referenced by