Skip to main content

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 like modified, permanent, new, and accessed which 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 and SessionMixin. If it returns None, Flask falls back to a NullSession.
  • save_session: Called at the end of every request. This is where you persist data to your backend and update the client's cookie using response.set_cookie.

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_session returns None (e.g., due to a configuration error), Flask uses NullSession. Any attempt to modify a NullSession will 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 accessed attribute. If you are implementing a custom backend, ensure your session object correctly updates self.accessed = True when data is read so that downstream caches can correctly handle the Vary: Cookie header.
  • 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_session will overwrite previous changes. Consider implementing locking in your backend if this is a concern.