Sessions in Flask: A Complete Guide with Redis and Examples

- Andrés Cruz - ES En español

Video thumbnail

When developing a web application with Flask, an inevitable moment arrives: we need to maintain user information between requests. Whether it is knowing who logged in, what is in their shopping cart, or what preferences they configured. This goes far beyond flash messages in Flask, which only persist for a single request.

That is where the session in Flask comes into play: a lightweight and very practical tool to manage temporary user data, either on the server side or the client side, depending on the configuration you choose.

In essence, the session serves to store information related to a specific user throughout their navigation. Data such as their name, unique identifier, or preferences can live in the session without needing to query them on every request. We will use it extensively in later chapters, especially in the authentication flow.

A classic use case, and perhaps the most common one, is the shopping cart: each product the user adds is recorded in the session until they checkout or close the browser.

Something important to keep in mind: session data is temporary. The session has a configured or implicit expiration date, and it will eventually expire.

Additionally, the session changes dynamically throughout the user's lifecycle: it is created when they log in, updated when any data changes, and destroyed when they log out or complete a purchase.

What is a session in Flask and what is it for?

A session is a temporary storage space that keeps information between different HTTP requests. In Flask, each user has their own session, identified by a secure cookie signed with a secret key.

For example, when a user successfully logs in, their name or ID is saved in the session to recognize them on every subsequent visit. In my case, I usually use it for exactly that: storing authenticated user data without having to ask for it again on every page or make an extra database query.

To use the session, it is necessary to set a secret key (secret_key), which Flask uses to cryptographically sign the cookie's content. This ensures that the client cannot manipulate the session data. This key must be defined from the beginning of the project, either directly in the main file or in your custom configuration file in Flask:

app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

Key operations with Flask Session

To manage your sessions efficiently, these are the most common operations you will use in your routes and controllers:

ActionCode
Read datasession.get('key')
Write / Savesession['key'] = 'value'
Delete datasession.pop('key', None)
Clear entire session (Logout)session.clear()

Considerations for mobile apps (Flutter / React Native)

If you are consuming your Flask API from a mobile application like Flutter or React Native, remember that although native apps do not usually have the same CORS restrictions as a web browser, when testing on emulators or integrated webviews, cookie and session handling may behave differently.

Best practices for sessions on mobile:

  • Do not blindly trust cookies: Some mobile platforms manage cookies volitily or directly do not persist them between sessions. For mobile apps, consider using JWT tokens instead of cookie-based sessions.
  • Configure preflight correctly: If your mobile app sends custom headers, make sure your Flask-CORS configuration allows OPTIONS requests.
  • Mandatory HTTPS with secure cookies: If you use SESSION_COOKIE_SECURE = True, your API must be served over HTTPS; otherwise, the session cookie will not be sent and the session will not be maintained on mobile devices.

⚠️ Note on object serialization in the session

Careful! Never attempt to store complex objects—such as SQLAlchemy instances or database models—directly in the session.

Flask serializes session content to JSON format to store it in the cookie. If you try to store an object that is not serializable, you will get an error like "Object of type X is not JSON serializable". The rule is simple: store only primitive data (strings, numbers, lists, dictionaries) or structures you can manually convert to JSON.

Differences between session and cookies in Flask

Although both allow storing information between HTTP requests, there are key differences that determine when to use one or the other:

AspectCookieSession
Data locationUser browser (plain text)Server (or encrypted in signed cookie)
SecurityLower — user can read itHigher — cryptographically signed
DurationAccording to configured expiration dateExpires automatically or when calling session.clear()

⚙️ Configuring the session in a Flask project

Before using the session, you need to configure the secret_key that Flask uses to sign cookies and prevent tampering. Without it, Flask will raise an error when attempting to access the session object.

You can define it directly in your main file:

from flask import Flask
app = Flask(__name__)
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

To use the session in any route, import the session object from Flask:

from flask import session

With that available, you can save data in the session just like in a Python dictionary:

session['username'] = 'user'

Retrieving a value is just as direct:

session['username']

And to delete a specific piece of data without destroying the entire session, use session.pop():

session.pop('username', None)

The second argument None prevents a KeyError from being raised if the key does not exist, which makes this pattern safe even if the user had previously logged out.

Practical examples of using session in Flask

To see it all together, here is a test module with three routes covering the complete cycle of a session: creating it, checking it, and deleting it:

from flask import Flask, session
app = Flask(__name__)
app.secret_key = 'clave_super_secreta'

@app.route('/test/session/set')
def test_session_set():
    session['username'] = 'user'
    return 'Session created for user'

@app.route('/test/session/check')
def test_session_check():
    if 'username' in session:
        return f'Authenticated user: {session["username"]}'
    return 'No active session'

@app.route('/test/session/pop')
def test_session_pop():
    session.pop('username', None)
    return 'Session deleted'

Test the three routes in order: first /test/session/set to create the session, then /test/session/check to verify it, and finally /test/session/pop to delete it. This gives you a clear idea of a session's lifecycle in Flask.

Maintaining user data after login

When a user successfully logs in, assigning their data to the session object is enough. This allows identifying them anywhere in the application throughout their active session, without needing to query the database on every request.

@app.route('/login', methods=['POST'])
def login():
    user = User.query.filter_by(email=request.form['email']).first()
    if user and user.check_password(request.form['password']):
        session['user_id'] = user.id
        session['username'] = user.name
        return redirect(url_for('dashboard'))
    return 'Invalid credentials', 401

The usual recommendation—and the one I follow—is to store only the user_id in the session and query the database when you need the full user details. This reduces cookie size and ensures data is always up to date.

️ Implementing a shopping cart with Flask Session

In another project, I used the session to store a list of products simply:

session['cart'] = ['Book A', 'Book B']

And upon checkout, it was enough to clear that data from the session:

session.pop('cart', None)

For a more complex cart (with quantities, prices, variants, etc.), you can store a list of dictionaries. Always remember to reassign the variable in the session after modifying it, since Flask does not automatically detect internal changes in mutable objects (see the arrays section below).

Flask-Session extension: server-side sessions

By default, Flask stores the entire session in a signed client cookie. This works well in small applications, but has a limit: cookies have a maximum size of 4 KB. If you need to store more data or want the session to persist on the server with greater control, the Flask-Session extension is the solution.

Installation and configuration of Flask-Session

$ pip install Flask-Session
from flask_session import Session
app.config['SESSION_TYPE'] = 'filesystem'
Session(app)

With SESSION_TYPE = 'filesystem', session data is saved in files on the server instead of the client cookie. This allows you to store larger objects and have greater control over expiration.

Usage with Redis and other storage options

For distributed or larger-scale applications, you can use SESSION_TYPE = 'redis' and point to a Redis server:

import redis

app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = redis.from_url('redis://localhost:6379')
Session(app)

Redis is ideal when you have multiple instances of your application running in parallel, as they all share the same session store. Other options available in Flask-Session are sqlalchemy, mongodb, and memcached.

Best practices and security in Flask Session

️ Avoiding exposure of sensitive data

Never store passwords, access tokens, or private information directly in the session. Use anonymous identifiers (like user_id) and, if you need to protect additional data, apply encryption before storing it.

⏱️ Controlling session expiration (session timeout)

You can configure the session lifetime using permanent_session_lifetime along with session.permanent = True:

from datetime import timedelta

app.permanent_session_lifetime = timedelta(minutes=30)

@app.route('/login')
def login():
    session.permanent = True
    session['user_id'] = user.id

Without session.permanent = True, the session expires upon closing the browser (browser session). With that line active, Flask respects the permanent_session_lifetime value and the session lasts for the configured time even if the user closes and reopens the browser.

Configuring secure cookies (SESSION_COOKIE_SECURE)

In production, always mark the session cookie as secure so it is only transmitted over HTTPS:

app.config['SESSION_COOKIE_SECURE'] = True
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'

SESSION_COOKIE_HTTPONLY = True prevents client-side JavaScript from accessing the cookie, protecting against XSS attacks. SESSION_COOKIE_SAMESITE = 'Lax' reduces the risk of CSRF attacks in most scenarios.

Storing arrays and multiple elements in the Flask session

The session in Flask is not limited to strings or numbers: you can store lists, dictionaries, or any data structure that is serializable to JSON. This opens the door to more complex use cases, such as maintaining a list of active elements per user without needing a database.

Flask provides the session object, which behaves like a normal Python dictionary. You can import it directly from the framework:

from flask import session

Saving multiple values in the session is as direct as this:

session['age'] = 30
session['name'] = "Andres"

Now, there is an important detail when working with lists inside the session: Flask does not automatically detect internal changes in mutable objects. If you modify a list or dictionary that is already in the session, you must explicitly reassign it so Flask marks it as modified and updates the cookie. The correct pattern is this:

def addRoomSession(room):
    if 'rooms' not in session:
        session['rooms'] = []

    rooms = session['rooms']    # 1. Get the list from the session
    rooms.append(room)          # 2. Modify the local list
    session['rooms'] = rooms    # 3. Reassign it so Flask detects the change
    print(session['rooms'])

def removeRoomSession(room):
    if 'rooms' not in session:
        return

    rooms = session['rooms']
    rooms.remove(room)
    session['rooms'] = rooms

The trick is in the reassignment at step 3. Without it, Flask might not save changes to the cookie because the object in memory is the same and the cookie is not marked as modified. An alternative is to manually set session.modified = True after any internal mutation, although explicit reassignment is clearer and more portable.

This code is part of my complete course on Flask, where we look at how to work with Flask-SocketIO and the concept of rooms, a real use case where the session plays a key role.

Conclusion

The session in Flask is an essential tool to maintain user data between requests without complicating the backend. Its combination of simplicity and security makes it perfect for managing logins, shopping carts, or any flow requiring temporary persistence.

If your project grows and the 4 KB cookie falls short, you can expand capacity with Flask-Session backed by Redis, ensuring scalability and total control over session data.

❓ Frequently Asked Questions about Flask Session (FAQ)

  • What happens if the server restarts?
    • Cookie-based sessions are maintained as long as the secret_key does not change. Server-side sessions (filesystem, Redis) can be lost if you do not use persistent storage or if the process restarts without configured persistence.
  • Can I store complex objects in the session?
    • Yes, but they must be serializable to JSON (lists, dictionaries, strings, numbers). SQLAlchemy objects or custom class instances are not directly serializable.
  • How do I delete all session data at once?
    • Use session.clear() to clear the session completely. This is the most common way to implement logout in Flask.
  • Is the session in Flask secure?
    • Yes, as long as you use a robust and random secret_key, enable SESSION_COOKIE_SECURE = True in production (with HTTPS), and avoid storing sensitive data directly in the session.
  • How do I decode a Flask session cookie?
    • The session cookie is Base64 encoded and signed with the secret_key, but not encrypted. You can view its content by decoding the part before the first dot using base64.b64decode(), but you cannot forge it without knowing the secret key. That is why it is critical that this key is complex and not exposed in public repositories.
  • What is the difference between session.pop() and session.clear()?
    • session.pop('key', None) deletes only the data with that key, leaving the rest of the session intact. session.clear() destroys the entire session at once, useful for implementing complete logout.

Recommendation: Store only the user identifier (user_id) in the session and, on each request, query your database to get the rest of the details. This keeps data always up to date and the cookie small.

The next step: learn how to use forms in Flask with WTForms.

Learn how to manage sessions in Flask step by step: how to save, read, and clear data using `session.clear()`, control timeouts, and use Flask-Session with Redis.


Únete a la comunidad de desarrolladores que han decidido dejar de picar código y empezar a construir productos reales. Recibe mis mejores trucos de arquitectura cada semana:

I agree to receive announcements of interest about this Blog.