brought to you by REVSYS

Caching Django Sessions

You better watch logs. You better not cry
Better not punt. I'm telling you why
Session Cache is coming to town

He's making a list(). And iterating it twice;
Gonna find out Who's caching or not
Session Cache is coming to town

It slows you when you're sleeping
It's slow when you're awake
It slows you if you've know or not
So cache it for goodness sake!

O! You better watch logs! You better not cry.
Better not punt. I'm telling you why
Session Cache is coming to town
Session Cache is coming to town
Session Cache by Abraham Lincoln

Checking it twice...

You know better than to use database backed sessions in Django right? Go check. No really, go check twice. It's super easy to overlook on systems of all sizes. We've done it, you're likely doing it and it makes the little Elves running your site work harder.

Just grep your settings file(s) for SESSION_ENGINE. If you don't find it, then you're putting your sessions in the database. Now go look at how HUGE that table is and have a quick sad.

Why it matters

There are several reasons this matters for sites of all sizes. If the kids on Santa's nice list make views that average 10 queries, then db sessions are eating up roughly 10% of the performance of your database AND you're likely not even using them for anything!!!

Other reasons:

  • If the user doesn't specifically log out, the database session row is never deleted. You think you gain some weight around the holidays? Just think how your django_session table feels.
  • Scaling your database is hard.
  • Memcached, by contrast, is super easy to scale.
  • It's quite simply the easiest performance thing you can do.

Many sites don't even have logged in users, but have sessions configured simply for their own access to the Django admin. While it's a bit more work, you too can avoid this pain by running another WSGI instance for the admin and removing the admin and sessions from your INSTALLED_APPS setting for your main WSGI instances. Don't worry, you can still have it live at /admin/ with an extra nginx proxy rule.

Setting up cached sessions in Django

You have a couple of choices make here. First, memcached or redis. If you are already using both with your system, just pick one, it doesn't really matter. If you currently aren't using either, go with redis. It's similar in speed and you'll likely find ways to use it's richer data structures down the road.

Secondly, you need to determine if your session data needs to be persistent at all.

Now let's setup Django with redis for our cache. You'll need to install it first with pip install django-redis-cache and then adjust your settings like this:

CACHES = {
    'default': {
        'BACKEND': 'redis_cache.RedisCache',
        'LOCATION': 'hostname:6379',
        'OPTIONS': {
            'DB': 1,
        },
    },
}

Now don't forget the advice from yesterday, if you're tempted to put localhost or 127.0.0.1 in for the hostname consider instead using unix sockets for a bit more speed. Another quick thing you can do is use HiRedis parser which is a wrapper around a faster library.

If you don't need persistent session data, you then just need to do this in your settings file:

SESSION_ENGINE = "django.contrib.sessions.backends.cache"

If you do need persistent sesions, you'll instead use:

SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"

Now go check again to make sure you're caching your sessions!

P.S.

I found out today that one of my favorite teachers Brad Simon died last Saturday. While I was always a bit of a geek, he took extra time to get me into HyperCard. Which eventually turned into programming as a hobby and eventually my career.

Oh and he also introduced me to the electric pickle. He's going to be missed. This post is dedicated to him.