Symfony – make sessions persistent over a LoadBalancing with your DB

By default, PHP (on which Symfony relies on) stores all sessions information on the filesystem.

However, when you scale-up your website, it is more likely that you’ll have multiple webservers behind a LoadBalancer. Having the sessions saved on the FileSystem will then lead to various issues (like being disconnected over requests).

To fix this, we have multiple ways.

Use the Database

One of the way to address this issue is to store all sessions informations into the Database. This ensure the datas are stored in a shared place that all WebServers can access at all time. However, this will add some strain on the DB.

To do so, you’ll need to edit the config/services.yaml file. In this, you shall add this portion of code:

# config/services.yaml
services:
    # ...

    Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler:
        arguments:
            - '%env(DATABASE_URL)%'

            # you can also use PDO configuration, but requires passing two arguments
            # - 'mysql:dbname=mydatabase; host=myhost; port=myport'
            # - { db_username: myuser, db_password: mypassword }

Then, edit the config/packages/framework.yaml file to set the SessionHandler to use PDO:

# config/packages/framework.yaml
framework:
    session:
        # ...
        handler_id: Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler

You can alter the columns that are used, if you need more customization over it, in the config/services.yaml :

# config/services.yaml
services:
    # ...

    Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler:
        arguments:
            - '%env(DATABASE_URL)%'
            - { db_table: 'customer_session', db_id_col: 'guid' }

Here is the list of the value you can change:

  • db_table (default sessions): The name of the session table in your database;
  • db_username: (default: '') The username used to connect when using the PDO configuration (when using the connection based on the DATABASE_URL env var, it overrides the username defined in the env var).
  • db_password: (default: '') The password used to connect when using the PDO configuration (when using the connection based on the DATABASE_URL env var, it overrides the password defined in the env var).
  • db_id_col (default sess_id): The name of the column where to store the session ID (column type: VARCHAR(128));
  • db_data_col (default sess_data): The name of the column where to store the session data (column type: BLOB);
  • db_time_col (default sess_time): The name of the column where to store the session creation timestamp (column type: INTEGER);
  • db_lifetime_col (default sess_lifetime): The name of the column where to store the session lifetime (column type: INTEGER);
  • db_connection_options (default: []) An array of driver-specific connection options;
  • lock_mode (default: LOCK_TRANSACTIONAL) The strategy for locking the database to avoid race conditions. Possible values are LOCK_NONE (no locking), LOCK_ADVISORY (application-level locking) and LOCK_TRANSACTIONAL (row-level locking).

Then, you’ll just have to run the migrations to create the Session DB 🙂