Flask sessions are usually stored in a cookie by default. This is fine for a single server, but when you scale out to multiple servers, users might hit different servers on subsequent requests, and their session data won’t be there. Redis is a great solution for this because it’s an in-memory data store that can be accessed by all your Flask servers.
Here’s a Flask app using Redis for session storage:
from flask import Flask, session, request, redirect, url_for
from flask_redis import FlaskRedis
import os
app = Flask(__name__)
# Configure Redis
app.config['REDIS_HOST'] = 'localhost'
app.config['REDIS_PORT'] = 6379
app.config['REDIS_DB'] = 0
app.secret_key = os.urandom(24) # Necessary for session encryption
redis_client = FlaskRedis(app)
@app.route('/')
def index():
if 'username' in session:
return f'Hello, {session["username"]}! <a href="/logout">Logout</a>'
return 'You are not logged in. <a href="/login">Login</a>'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return '''
<form method="post">
<p><input type="text" name="username"></p>
<p><input type="submit" value="Login"></p>
</form>
'''
@app.route('/logout')
def logout():
session.pop('username', None)
return redirect(url_for('index'))
if __name__ == '__main__':
app.run(debug=True)
To run this:
- Install Flask and Flask-Redis:
pip install Flask Flask-Redis - Make sure you have a Redis server running on
localhost:6379. - Run the Flask app:
python your_app_file.py
Now, when you visit http://127.0.0.1:5000/, you’ll see the login prompt. After logging in, your username will be stored in the session. If you were to run multiple instances of this Flask app (e.g., on different ports or servers) and have a load balancer directing traffic, subsequent requests from the same user would still find their session data in Redis.
The core problem this solves is maintaining user state across multiple, independent server instances. Without a shared session store like Redis, each server instance would have its own isolated session data (if using cookies or memory), meaning a user logged into Server A would appear logged out if their next request landed on Server B. By centralizing session data in Redis, any server instance can retrieve the correct session information for any user, enabling seamless scaling.
Internally, Flask-Redis intercepts Flask’s session management. When you call session['key'] = 'value', Flask-Redis serializes this data and stores it in a Redis key, typically prefixed with session:. When you later access session['key'], Flask-Redis retrieves the serialized data from Redis, deserializes it, and returns it. The app.secret_key is still crucial; it’s used to sign the session cookie itself, which contains a session ID. This ID is then used by Flask-Redis to look up the actual session data in Redis.
The primary levers you control are the Redis connection details (REDIS_HOST, REDIS_PORT, REDIS_DB) and the app.secret_key. The secret key is vital for security; it prevents session hijacking by ensuring that session cookies cannot be tampered with. A strong, randomly generated secret key is essential for production environments.
You might notice that even with Redis, there’s a specific way session data is structured and accessed. Flask’s session object behaves like a dictionary, but the underlying mechanism involves serialization and key-value storage in Redis. The keys in Redis are often derived from the session cookie’s content, making the cookie itself a pointer to the full session data.
When you configure Flask-Redis, it automatically hooks into Flask’s before_request and after_request handlers. before_request is where it attempts to load the session data from Redis based on the session cookie. after_request is where it saves any modified session data back to Redis. This transparently replaces the default cookie-based session handling.
The most surprising thing to many is how simple it is to swap out the session backend. Flask’s session interface is designed to be pluggable. You don’t need to rewrite large parts of your application logic; you just configure a different session interface, and Flask handles the rest. The Flask-Redis extension is a perfect example of this, abstracting away the Redis interaction so your app code remains clean.
The next step to consider is how to handle session expiration and cleanup in Redis.