Skip to main content

Managing Session Lifetime and Persistence

To manage session lifetime and persistence in Flask, you use the SessionMixin attributes provided by the session object. These attributes allow you to control whether a session persists after the browser closes and track whether the session data has been read or changed during a request.

Making Sessions Permanent

By default, Flask sessions are "browser sessions," meaning they expire when the user closes their browser. To create a long-lived session, set session.permanent to True.

from flask import Flask, session

app = Flask(__name__)
app.secret_key = "example-key"

@app.route("/login")
def login():
# This session will now persist according to PERMANENT_SESSION_LIFETIME
session["user_id"] = 123
session.permanent = True
return "Logged in"

When permanent is True, Flask uses the PERMANENT_SESSION_LIFETIME configuration (default is 31 days) to set the cookie's expiration.

Tracking Session Access and Modification

Flask uses flags on the SessionMixin to optimize how and when it sends session cookies back to the client.

  • session.accessed: Automatically set to True whenever the session is read. If this is True, Flask adds a Vary: Cookie header to the response to ensure downstream caches handle the response correctly.
  • session.modified: Set to True whenever a key is set or deleted in the session dictionary. Flask only sends a Set-Cookie header if modified is True (or if the session is permanent and SESSION_REFRESH_EACH_REQUEST is enabled).

You can check these flags to see if the session was touched during a request:

@app.route("/check-session")
def check_session():
# Accessing the session sets 'accessed' to True
print(f"Accessed: {session.accessed}")

# Modifying the session sets 'modified' to True
session["last_visit"] = "now"
print(f"Modified: {session.modified}")

return "Checked"

Handling Nested Mutable Objects

Flask's default session implementation (based on werkzeug.datastructures.CallbackDict) only detects changes to the top-level session dictionary. If you modify a mutable object stored inside the session, such as a list or a dictionary, you must manually set session.modified = True.

@app.route("/add-item")
def add_item():
if "cart" not in session:
session["cart"] = []

# Modifying the list directly won't be detected by Flask
session["cart"].append("new-item")

# Manually signal that the session has changed
session.modified = True
return "Item added"

Custom Persistence Logic

If you implement a custom SessionInterface, you can use these flags in your save_session method to decide how to persist data. The SessionInterface provides helper methods that rely on these attributes:

  • should_set_cookie(): Returns True if session.modified is set, or if the session is permanent and configured to refresh on every request.
  • get_expiration_time(): Returns a datetime object if session.permanent is True, otherwise returns None.
from flask.sessions import SessionInterface, SessionMixin

class MySessionInterface(SessionInterface):
def save_session(self, app, session, response):
# Use the mixin's accessed flag to set Vary header
if session.accessed:
response.vary.add("Cookie")

# Use the mixin's modified flag to decide if we need to save
if not self.should_set_cookie(app, session):
return

# Use the mixin's permanent flag to calculate expiration
expires = self.get_expiration_time(app, session)

# ... logic to save session data and set cookie ...

Configuration Reference

The behavior of SessionMixin attributes is influenced by these application settings:

ConfigurationDefaultDescription
PERMANENT_SESSION_LIFETIMEtimedelta(days=31)The duration of a session when session.permanent is True.
SESSION_REFRESH_EACH_REQUESTTrueIf True and the session is permanent, a Set-Cookie header is sent on every request to refresh the expiration.
SESSION_COOKIE_NAME"session"The name of the cookie used to store the session.