The Session Management Crisis
Performance Problem
Your D2C brand launches a Black Friday flash sale. Traffic spikes 50x. Suddenly, users can't add items to their carts. The server CPU is fine, RAM is fine, but the checkout is spinning.
The Culprit: Disk I/O on session files.
Security Problem
A support agent logs into Odoo on a shared warehouse terminal. They forget to log out. Three days later, a temp worker sits down and finds they still have full admin access to your customer database.
The Culprit: Default session lifetimes.
We've implemented 150+ Odoo systems. Session management is the silent killer of both scalability and security. Most developers stick with the defaults until the site crashes or an audit fails.
How Odoo Sessions Work (Under the Hood)
By default, Odoo uses File-Based Storage for sessions.
The Flow
The Cookie: When a user logs in, Odoo sets a session_id cookie in the browser
The Storage: On the server, Odoo creates a specialized "pickle" file (Python object serialization) in /var/lib/odoo/sessions/
The Lookup: Every click reads cookie, finds matching file on disk, deserializes into RAM, processes request, saves back to disk
Why This Works for Small Companies
✓ Simple - requires zero configuration
Why This Fails for D2C Brands
Disk I/O: Reading/writing files thousands of times per second locks the file system
Latency: Disk is always slower than RAM
Clustering: If you have 2 Odoo servers behind load balancer, Server A has session file but Server B doesn't. Forced to use "Sticky Sessions" (IP Hash) = uneven load balancing
The Performance Fix: Redis Session Store
For high-traffic D2C brands, you must move sessions off the disk and into RAM. The industry standard is Redis.
Why Redis?
| Feature | Benefit |
|---|---|
| Speed | In-memory key-value store, sub-millisecond reads |
| Concurrency | No file locking issues |
| Scalability | Multiple Odoo workers/servers share same session state |
Implementation: Odoo doesn't support Redis out of the box in odoo.conf without a library. You typically use a customized session_store. There are several community modules for this, or you can override http.root.session_store.
Concept Code (Session Store Override)
# In your custom module's __init__.py or a monkey-patch file
import odoo
from odoo.tools.config import config
import redis
try:
import cPickle as pickle
except ImportError:
import pickle
class RedisSessionStore(object):
def __init__(self, redis_url):
self.redis = redis.from_url(redis_url)
def get(self, sid):
data = self.redis.get(sid)
return pickle.loads(data) if data else None
def save(self, session):
self.redis.setex(session.sid, 60*60*24*7, pickle.dumps(session))
def delete(self, sid):
self.redis.delete(sid)
# Hooking it into Odoo (Simplified for illustration)
if config.get('session_store_type') == 'redis':
odoo.http.root.session_store = RedisSessionStore(config.get('redis_url'))
Real-World Impact
We migrated a client doing 5,000 orders/day from File Storage to Redis.
| Metric | Before | After | Improvement |
|---|---|---|---|
| Checkout Load Time | 1.8s | 0.4s | 4.5x faster |
| Server CPU Usage | Baseline | -15% | Less I/O wait |
The Security Fix: Enforcing Timeouts
Odoo's default session behavior is "keep me logged in for a week." For a warehouse or finance terminal, this is a security violation (PCI-DSS/GDPR).
You need to enforce an Idle Timeout. If the user doesn't click anything for 15 minutes, kill the session.
The Solution: Custom ir.http Override
Do not rely on JavaScript frontend timers (knowledgeable users can disable them). Enforce this at the server level.
from odoo import models, http, fields
from odoo.http import request
import time
SESSION_TIMEOUT = 900 # 15 Minutes in seconds
class IrHttp(models.AbstractModel):
_inherit = 'ir.http'
@classmethod
def _auth_method_user(cls):
# Perform standard authentication first
super()._auth_method_user()
# Check for Idle Timeout
if request.session.uid:
last_request = request.session.get('last_request_time', 0)
now = time.time()
# If session is old AND user is not a public user
if last_request and (now - last_request) > SESSION_TIMEOUT:
# Kill the session
request.session.logout()
request.session.rotate = True # Force new session ID
# Redirect to login
raise http.SessionExpiredException("Session timed out due to inactivity.")
# Update last request time
request.session['last_request_time'] = now
Configuration Tip
Don't hardcode 900. Use ir.config_parameter so your System Admin can change the timeout without restarting code.
timeout = int(request.env['ir.config_parameter'].sudo().get_param('session.timeout', 900))
Securing the Cookie (odoo.conf)
Even if your session logic is perfect, if the cookie travels over HTTP, it can be hijacked.
Ensure your odoo.conf and Nginx settings enforce cookie security.
1. Proxy Mode
If you are behind Nginx/AWS ALB (which you should be), tell Odoo it's being proxied so it handles HTTPS correctly.
proxy_mode = True
2. Nginx Headers
Ensure Nginx passes the protocol.
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
3. Cookie Flags (SameSite & Secure)
Modern browsers block cookies that don't look secure. Odoo 16+ handles SameSite=Lax by default, but verify your headers using browser DevTools.
Your Action Items
Performance Audit
❏ Check /var/lib/odoo/sessions. Is it huge? (GBs of files)
❏ If you have >50 concurrent users, plan a migration to Redis
Security Audit
❏ Log in to Odoo. Close the tab. Come back 2 days later. Are you still logged in?
❏ If yes, and you handle sensitive customer data, implement the Idle Timeout override immediately
Configuration
❏ Verify proxy_mode = True in your production config
❏ Check that your load balancer is using HTTPS termination
Free Infrastructure & Security Audit
Session management is invisible until it fails. We'll analyze your current session storage (Disk vs RAM), stress-test your session handling under load, attempt a "Session Hijack" simulation to test your cookie security, and implement the 15-minute idle timeout logic for you. Don't let a stale cookie compromise your database.
