# PHP Sessions in Redis for Multiple Web Servers

> PHP sessions in Redis: how to configure session.save_handler, install php-redis, and stop losing sessions behind a load balancer.

## Why Store PHP Sessions in Redis Across Multiple Servers

The default PHP session handler writes files to the /var/lib/php/sessions directory on the local disk of the server. As long as the application runs on a single machine, this is not a problem. As soon as a load balancer puts two or more web servers behind it, a user's next request can land on a different server and lose the session: the file with its data stayed on the first host.

The solution is to move session storage outside the local disk into a shared store available to all servers at once. Redis suits this better than the NFS file system: it keeps data in memory, responds in fractions of a millisecond, and supports TTL out of the box, so expired sessions get removed automatically. Setting up web servers with Nginx and PHP-FPM, for example following the scheme from the article [Laravel on a server with Nginx](https://www.zevshost.net/en/kb/laravel-nastroika-vps-nginx/), usually leads to exactly this need for shared session storage.

## How to Enable Redis as the Session Handler

PHP can work with Redis as session.save\_handler without any extra code in the application — two directives in php.ini or in the PHP-FPM pool are enough. The first sets the handler itself, the second the connection address.

```
session.save_handler = redis
session.save_path = "tcp://127.0.0.1:6379?timeout=2.5&persistent=1"
```

The persistent=1 parameter keeps the connection to Redis open between PHP-FPM requests and saves time on establishing a TCP connection. If Redis runs on a separate server instead of locally, replace 127.0.0.1 with its internal IP address and be sure to close port 6379 from the outside world with firewall rules.

## Installing the php-redis Module and Checking It

The session.save\_handler = redis directive will not work on its own — you need the php-redis extension built for the installed PHP version.

```
apt install php-redis
systemctl restart php8.3-fpm
php -m | grep redis
```

If the server runs several PHP versions at once, install the extension for each version separately — the details of such a setup are covered in the article [on running multiple PHP versions on one server](https://www.zevshost.net/en/kb/php-multi-version-linux/). After installation, restart the PHP-FPM pool, otherwise the workers will keep using the old module list for hours.

## session.save\_path Parameters for Redis

The connection string supports several parameters joined with an ampersand. Below are the ones that actually matter in production.

| Parameter | Example | Purpose |
| --- | --- | --- |
| timeout | 2.5 | Connection timeout to Redis, in seconds |
| persistent | 1 | Keep the connection open between requests |
| weight | 1 | Server weight when using several Redis nodes |
| prefix | sess\_ | Prefix for session keys in a shared Redis database |

Always set a prefix if the same Redis database also holds application cache data: without it, session keys and cache keys are easy to mix up when clearing with the FLUSHDB command.

## Common Mistakes When Moving Sessions to Redis

- Forgetting to restart PHP-FPM after editing php.ini — old workers keep writing sessions to files.
- Redis is configured without a password and listens on 0.0.0.0 — every user's session is reachable from the internet.
- No maxmemory-policy is set, so Redis starts evicting session keys like ordinary cache when memory runs low.
- The session ID is passed in the URL instead of a cookie — someone else's session ends up in logs and browser history.
- Servers have different clocks (no NTP sync), which makes the session TTL count incorrectly.

## Summary: Checklist for Moving Sessions to Redis

- session.save\_handler = redis and session.save\_path are identical on every web server.
- The php-redis extension is installed and enabled for every PHP version in use.
- Redis is protected with a requirepass password and closed off by the firewall from outside connections.
- A maxmemory-policy of noeviction or volatile-ttl is set for the database that holds sessions.
- After the changes, PHP-FPM was restarted and phpinfo confirms sessions are indeed written to Redis.

---

Source: https://www.zevshost.net/en/kb/php-sessii-v-redis/
