DEV Community

Magevanta
Magevanta

Posted on • Originally published at magevanta.com

Magento 2 Session Storage Optimization: Redis, Files, and Database Sessions Compared

Session management is one of those quiet performance killers that rarely gets attention until your store starts grinding under load. By default, Magento 2 stores sessions on the filesystem — a setup that works fine for a single-server development environment but falls apart fast in production. In this guide, we'll break down every viable session storage option, benchmark the trade-offs, and show you exactly how to configure Redis sessions the right way.

Why Session Storage Matters

Every visitor to your Magento store — logged-in or guest — gets a session. That session tracks their cart, wishlist, recently viewed products, and authentication state. On a busy store handling thousands of concurrent visitors, the overhead of reading and writing session data adds up fast.

The three main options are:

  1. Filesystem sessions — the default, stored in var/session/
  2. Database sessions — stored in the session table in MySQL
  3. Redis sessions — stored in memory via a dedicated Redis instance

Let's go through each in detail.

Filesystem Sessions

This is what you get out of the box. Magento writes a file per session to var/session/ using PHP's built-in file session handler.

Pros:

  • Zero configuration
  • Works immediately with no dependencies
  • Easy to inspect for debugging

Cons:

  • Does not scale to multiple web nodes (sessions are local to one server)
  • File system I/O becomes a bottleneck under load
  • No built-in expiration management — old session files accumulate and must be cleaned with cron
  • Prone to race conditions under concurrent requests from the same session

On a single-server setup with moderate traffic (under ~100 concurrent users), filesystem sessions are acceptable. Beyond that, you're leaving performance on the table.

Database Sessions

Magento 2 supports storing sessions in the MySQL session table by setting the session save handler to db.

// app/etc/env.php
'session' => [
    'save' => 'db',
],
Enter fullscreen mode Exit fullscreen mode

Pros:

  • Works across multiple web nodes
  • Data is persistent across server restarts
  • Session locking is handled correctly

Cons:

  • Adds load to your MySQL server — often the most constrained resource
  • Table grows without bound; requires aggressive cleanup
  • Much slower than Redis for read/write operations (disk I/O vs memory)
  • Locking overhead on high-concurrency stores

Database sessions are a step up from filesystem if you need multi-server support but can't run Redis. In practice, they're rarely the right long-term choice because they shift bottleneck load onto MySQL.

Redis Sessions — The Right Choice for Production

Redis is an in-memory data store, and it's the recommended session backend for any Magento 2 production environment. Magento ships with a built-in Redis session handler (Cm_RedisSession) from Magento 2.0.

Why Redis Wins

  • Speed: Memory operations are orders of magnitude faster than disk or database I/O
  • Automatic expiry: TTL-based expiration means no manual session cleanup
  • Multi-node safe: All web servers share the same session store
  • Concurrency handling: Built-in advisory locking prevents session corruption
  • Monitoring: Redis CLI and tools like RedisInsight give full visibility into session data

Benchmark Context

On a typical Magento 2 store under load test (500 concurrent users, mixed cart/browse traffic):

Backend Avg. session read (ms) Avg. session write (ms) Server CPU impact
Filesystem 8–15 12–20 Low (disk I/O)
MySQL DB 15–40 20–50 High (query load)
Redis 0.3–1 0.5–1.5 Minimal

These numbers vary by hardware, but the pattern is consistent: Redis session I/O is 10–50x faster than alternatives.

Configuring Redis Sessions in Magento 2

Prerequisites

  • Redis installed and running (typically on port 6379)
  • A separate Redis instance or database number for sessions vs. full page cache (important — see below)

Basic Configuration

Edit app/etc/env.php:

'session' => [
    'save' => 'redis',
    'redis' => [
        'host' => '127.0.0.1',
        'port' => '6379',
        'password' => '',
        'timeout' => '2.5',
        'persistent_identifier' => '',
        'database' => '2',
        'compression_threshold' => '2048',
        'compression_library' => 'gzip',
        'log_level' => '1',
        'max_concurrency' => '6',
        'break_after_frontend' => '5',
        'break_after_adminhtml' => '30',
        'first_lifetime' => '600',
        'bot_first_lifetime' => '60',
        'bot_lifetime' => '7200',
        'disable_locking' => '0',
        'min_lifetime' => '60',
        'max_lifetime' => '2592000',
        'sentinel_master' => '',
        'sentinel_servers' => '',
        'sentinel_connect_retries' => '5',
        'sentinel_verify_master' => '0',
    ],
],
Enter fullscreen mode Exit fullscreen mode

Key Parameters Explained

database — Use a different number (0, 1, 2...) than your default cache and full page cache Redis instances. Mixing them makes TTL and memory management a nightmare.

max_concurrency — Maximum number of processes that can wait for a session lock at once. The default of 6 is fine for most stores. Lower it on smaller servers to avoid Redis connection exhaustion.

break_after_frontend — Seconds to wait before breaking a session lock on the frontend. A value of 5 is aggressive but prevents hung requests from blocking the cart.

disable_locking — Leave this at 0. Disabling session locking speeds things up but causes data corruption on concurrent AJAX requests (e.g., add-to-cart + minicart update firing simultaneously).

compression_threshold — Session data over this size in bytes gets compressed. Reduces Redis memory usage for stores with large cart data or extensive customer session payloads.

bot_first_lifetime / bot_lifetime — Short TTLs for detected bots. This alone can dramatically reduce Redis memory usage on high-traffic stores where crawlers represent 20–40% of sessions.

Separating Sessions from Cache in Redis

A common mistake is pointing both cache and session at the same Redis instance with the same database number. This causes:

  • Sessions and cached HTML blocks competing for memory
  • When Redis hits maxmemory, eviction policies may delete session data
  • Harder to tune TTLs independently

Recommended setup:

Redis DB 0 → Default cache (blocks, collections, config)
Redis DB 1 → Full Page Cache
Redis DB 2 → Sessions
Enter fullscreen mode Exit fullscreen mode

Or use separate Redis ports/instances if your server has the memory to support it. For session storage, configure maxmemory-policy noeviction — you never want Redis silently dropping sessions because it ran out of memory. Size your Redis instance accordingly.

Redis Sentinel for High Availability

If your store needs zero-downtime session persistence, Redis Sentinel provides automatic failover. Magento 2 supports Sentinel natively through the same env.php configuration:

'sentinel_master' => 'mymaster',
'sentinel_servers' => '192.168.1.10:26379,192.168.1.11:26379,192.168.1.12:26379',
Enter fullscreen mode Exit fullscreen mode

For most Magento stores, a single Redis instance with persistence (appendonly yes in redis.conf) is sufficient. Sentinel adds operational complexity that's only worth it at significant scale.

Session Lifetime Tuning

Session lifetime directly affects how long customers stay "logged in" and how much memory Redis consumes.

'max_lifetime' => '2592000', // 30 days — good for B2C
'first_lifetime' => '600',   // 10 min for new/guest sessions
Enter fullscreen mode Exit fullscreen mode

For B2B Magento stores with account-heavy workflows, longer lifetimes (90 days) reduce friction. For high-traffic B2C stores, shorter guest session lifetimes aggressively keep Redis memory usage down.

Run this command to check your current session count and memory usage:

redis-cli -n 2 info keyspace
redis-cli -n 2 dbsize
redis-cli info memory | grep used_memory_human
Enter fullscreen mode Exit fullscreen mode

Flushing Sessions Safely

Never run redis-cli flushall in production — it wipes all Redis data including cache. To flush only sessions:

redis-cli -n 2 flushdb
Enter fullscreen mode Exit fullscreen mode

To expire sessions for a specific customer (useful for security incidents), find and delete their session key:

redis-cli -n 2 keys "sess_*" | head -20
redis-cli -n 2 del sess_<session_id>
Enter fullscreen mode Exit fullscreen mode

Verifying Your Configuration

After updating env.php, flush config and verify Redis is receiving session writes:

php bin/magento cache:flush config
redis-cli -n 2 monitor
Enter fullscreen mode Exit fullscreen mode

Open your store in a browser and watch redis-cli monitor — you should see SET sess_* and GET sess_* commands flowing in.

Summary

Filesystem MySQL DB Redis
Speed Medium Slow Fast
Multi-server No Yes Yes
Auto-expiry No No Yes
Memory safe Yes Yes Needs tuning
Recommended Dev only Fallback Production

If you're running Magento 2 in production and haven't switched to Redis sessions yet, it's the single highest-impact configuration change you can make with the least risk. It's well-supported, well-documented, and the performance difference under real traffic is immediately measurable.

Start with a separate Redis database number, configure sane TTLs for bots and guests, and make sure maxmemory-policy is set to noeviction for the session database. Your checkout conversion rate (and your ops team) will thank you.

Top comments (0)