Enabling CodeIgniter's Garbage Collector

My session driver of choice for CodeIgniter is database. A while ago, I noticed millions of rows in the corresponding database table. That means that garbage collector was not working. I checked config.php for sess_regenerate_destroy, but it was already set to false. It was really weird because the problem seemed to have come out of nowhere – not much ago things were working just fine.

After a short investigation, I found out this was and still is a common problem for those who had upgraded their CodeIgniter version from 2.x to 3.x. Turns out, the later possesses heavy changes for Sessions library. And most importantly – fundamental changes in dealing with garbage: CodeIgniter 3.x relies on PHP's native grabage collector. So, in order to get things working again, we need to configure PHP properly.

The Solution

Today there are three PHP-native settings for dealing with session garbage collector. CodeIgniter's Session library has already taken care of one of them – gc_maxlifetime – so there's no need for an extra touch here. The problem lies within the rest: session.gc_probability and/or session.gc_divisor. These two determine when the garbage collector is running. Here's what php.net says:

session.gc_divisor coupled with session.gc_probability defines the probability that the gc (garbage collection) process is started on every session initialization. The probability is calculated by using gc_probability/gc_divisor, e.g. 1/100 means there is a 1% chance that the GC process starts on each request.

In my case, using ini_get() revealed the following values: 0 and 1000. The equation 0/1000=0 meant there was no chance the garbage collector would even run.

Finally, I solved the problem by using the values officially stated as default and by putting the following lines of PHP code into config/config.php file:

ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 100);

Theoretically, this means that the garbage collector usually runs once every 100th request. It's more than enough, but it is up to you whether that causes too many unnecessary hits to database. An alternative solution for heavy-traffic websites could be having a 0% probability on the production site and a Cronjob-based script which removes database rows of the expired sessions.