Implementing Custom Session Backends
To replace the default cookie-based session management in Flask, you must implement a custom SessionInterface and assign it to your application's session_interface attribute.
Implementing a Custom Session Backend
The following example demonstrates a basic custom session implementation using a dictionary-backed store.
import flask
from flask.sessions import SessionInterface, SessionMixin
class MySession(dict, SessionMixin):
"""A custom session object that tracks modification and permanence."""
def __init__(self, initial=None, sid=None):
super().__init__(initial or {})
self.sid = sid
class MySessionInterface(SessionInterface):
def open_session(self, app, request):
# Retrieve the session ID from the cookie
sid = request.cookies.get(self.get_cookie_name(app))
if not sid:
# Return a new session object if no ID is found
return MySession(sid="new-session-id")
# Load session data from your backend (e.g., Redis, Database)
# For this example, we use a dummy data dict
data = {"user_id": 42}
return MySession(data, sid=sid)
def save_session(self, app, session, response):
domain = self.get_cookie_domain(app)
path = self.get_cookie_path(app)
# If the session was deleted, remove the cookie
if not session:
if session.modified:
response.delete_cookie(
self.get_cookie_name(app),
domain=domain,
path=path
)
return
# Only update the cookie if the session was modified or is permanent
if not self.should_set_cookie(app, session):
return
# Save session data to your backend here
# ...
# Set the session cookie on the response
response.set_cookie(
self.get_cookie_name(app),
session.sid,
expires=self.get_expiration_time(app, session),
httponly=self.get_cookie_httponly(app),
domain=domain,
path=path,
secure=self.get_cookie_secure(app),
samesite=self.get_cookie_samesite(app),
)
app = flask.Flask(__name__)
app.session_interface = MySessionInterface()
Key Components
SessionMixin: Your session object must include this mixin. It provides essential attributes likemodified,permanent,new, andaccessedwhich Flask uses to manage the session lifecycle.open_session: Called at the start of every request. It must return an object that implements a dictionary-like interface andSessionMixin. If it returnsNone, Flask falls back to aNullSession.save_session: Called at the end of every request. This is where you persist data to your backend and update the client's cookie usingresponse.set_cookie.
Dynamic Cookie Configuration
If you want to keep the default signed-cookie logic but change specific behaviors like the cookie name based on the request, extend SecureCookieSessionInterface.
from flask.sessions import SecureCookieSessionInterface
import flask
class PathAwareSessionInterface(SecureCookieSessionInterface):
def get_cookie_name(self, app):
# Change cookie name based on the request URL
if flask.request.url.endswith("dynamic_cookie"):
return "dynamic_cookie_name"
return super().get_cookie_name(app)
app = flask.Flask(__name__)
app.session_interface = PathAwareSessionInterface()
Accessing Request Information in open_session
By default, sessions are opened before URL matching occurs. If your open_session logic depends on the matched endpoint or URL rule, you must manually trigger request matching using app_ctx.match_request().
from flask.globals import app_ctx
from flask.sessions import SessionInterface
class MatchAwareSessionInterface(SessionInterface):
def open_session(self, app, request):
# Manually trigger matching to populate request.endpoint
app_ctx.match_request()
if request.endpoint == 'secret_route':
# Perform specific session logic for this route
pass
return super().open_session(app, request)
Troubleshooting and Gotchas
- NullSession Errors: If
open_sessionreturnsNone(e.g., due to a configuration error), Flask usesNullSession. Any attempt to modify aNullSessionwill raise an error (e.g., "The session is unavailable because no secret key was set"). - Vary: Cookie Header: Flask's request context tracks if the session was accessed via the
accessedattribute. If you are implementing a custom backend, ensure your session object correctly updatesself.accessed = Truewhen data is read so that downstream caches can correctly handle theVary: Cookieheader. - Synchronization: Flask does not synchronize session access across concurrent requests. If multiple requests for the same session are handled simultaneously, the last one to call
save_sessionwill overwrite previous changes. Consider implementing locking in your backend if this is a concern.