PHP Session Handling on Heroku

Most web applications use sessions of some kind for things like login systems, authentication, flash messages, etc. But using them on cloud services like Heroku can sometimes be a hastle. This post will hopefully outline some of the different methods you can use to get a fast, adaptable and easy session handler with PHP.

Option 1) Single Dyno, Default Session (File)#

By simply running session_start(); with PHP, by default a file based session will start. This is great because it’s easy to setup. The performance of this is considered slower than technologies like Memcache and Redis (which store data in RAM not onto disk), however it is often faster than using a remote session service because of network overhead (from my limited experience(.

They do however have a disadvantage in that because they store the session to file, when deployed to cloud based infrastructures like Heroku, the session won’t be shared across the dynos or instances – meaning you’re session id will change as you load from different dynos. This makes developing things like login systems very difficult. It also has the disadvantage of being wipped clean on a new deployment (because the dyno is re-built).

So, what’s the alternative?

Option 2) Memcache/Memcachier#

Memcached (the extension) and Memcachier (the provider/service) are a great alternatives to file based sessions. They are quick, robust and easy enough to setup. Heroku has a guide on how to set these up. The brief version of the guide being that you need the ext-memcached extension enabled within your composer file and some modifications are needed to the .user.ini file to change the session provider to memcache. You’ll still need to call session_start() but everything will be handled for you.

{
    "require": {
        "ext-memcached": "*"
    }
}
session.save_handler=memcached
session.save_path=${MEMCACHIER_SERVERS}
memcached.sess_binary=1
memcached.sess_sasl_username=${MEMCACHIER_USERNAME}
memcached.sess_sasl_password=${MEMCACHIER_PASSWORD}

Option 3) Predis#

In differentiation to memcache, Predis is a php based library which can be used to change sessions management to be stored within Redis. This means a php extension is not needed – which can be a big advantage if the php extension’s support is lacking for the php version you are using, or the infrastructure you use does not support the extension. This is however often a slower method of session handling as the logic is run by the php interpreter – and not compiled into a C extension.

Example Predis Session Handler:

<?php

// Instantiate a new client just like you would normally do. Using a prefix for
// keys will effectively prefix all session keys with the specified string.
$client = new Predis\Client($single_server, array('prefix' => 'sessions:'));

// Set `gc_maxlifetime` to specify a time-to-live of 5 seconds for session keys.
$handler = new Predis\Session\Handler($client, array('gc_maxlifetime' => 5));

// Register the session handler.
$handler->register();

// We just set a fixed session ID only for the sake of our example.
session_id('example_session_id');
session_start();

if (isset($_SESSION['foo'])) {
    echo "Session has `foo` set to {$_SESSION['foo']}", PHP_EOL;
} else {
    $_SESSION['foo'] = $value = mt_rand();
    echo "Empty session, `foo` has been set with $value", PHP_EOL;
}