Configure Django Redis caching and session storage for high-performance web applications

Intermediate 25 min May 16, 2026 55 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up Redis as both cache backend and session storage for Django applications. Improve page load times and user experience with proper Redis configuration and Django integration.

Prerequisites

  • Django application running
  • Python pip package manager
  • Root or sudo access

What this solves

Django's default database sessions and no caching can create performance bottlenecks under load. This tutorial configures Redis as both Django's cache backend and session storage, reducing database queries and improving response times for high-traffic applications.

Step-by-step installation

Update system packages

Start by updating your package manager to ensure you get the latest versions.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install Redis server

Install Redis server and client libraries for your system.

sudo apt install -y redis-server redis-tools
sudo dnf install -y redis redis-tools epel-release

Configure Redis for production

Set up Redis with optimized settings for Django caching and sessions.

# Memory configuration
maxmemory 256mb
maxmemory-policy allkeys-lru

Persistence settings for sessions

save 900 1 save 300 10 save 60 10000

Network settings

bind 127.0.0.1 port 6379 tcp-keepalive 300

Security

requirepass your_secure_redis_password

Performance tuning

tcp-backlog 511 timeout 0 keepalive 300

Enable and start Redis

Enable Redis to start on boot and start the service.

sudo systemctl enable redis-server
sudo systemctl start redis-server
sudo systemctl status redis-server

Install Python Redis clients

Install the Redis Python client and Django Redis integration library.

pip install redis django-redis hiredis

Configure Django caching backend

Add Redis cache configuration to your Django settings file.

CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'PASSWORD': 'your_secure_redis_password',
            'CONNECTION_POOL_KWARGS': {
                'max_connections': 50,
                'retry_on_timeout': True,
            }
        },
        'KEY_PREFIX': 'myapp',
        'VERSION': 1,
        'TIMEOUT': 300,  # 5 minutes default timeout
    }
}

Use Redis for session caching too

SESSION_ENGINE = 'django.contrib.sessions.backends.cache' SESSION_CACHE_ALIAS = 'default' SESSION_COOKIE_AGE = 1209600 # 2 weeks

Configure Redis session storage

Set up dedicated Redis database for session storage with different configuration.

# Alternative: Separate Redis instance for sessions
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'PASSWORD': 'your_secure_redis_password',
        },
        'KEY_PREFIX': 'cache',
        'TIMEOUT': 300,
    },
    'sessions': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/2',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'PASSWORD': 'your_secure_redis_password',
        },
        'KEY_PREFIX': 'session',
        'TIMEOUT': 1209600,  # 2 weeks
    }
}

Use dedicated session cache

SESSION_ENGINE = 'django.contrib.sessions.backends.cache' SESSION_CACHE_ALIAS = 'sessions'

Add caching middleware

Enable Django's caching middleware for automatic page caching.

MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
]

Cache settings

CACHE_MIDDLEWARE_ALIAS = 'default' CACHE_MIDDLEWARE_SECONDS = 600 CACHE_MIDDLEWARE_KEY_PREFIX = ''

Enable template fragment caching

TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], 'builtins': [ 'django.templatetags.cache', ], }, }, ]

Optimize Redis memory usage

Configure Redis to handle Django's specific caching patterns efficiently.

# Optimize for Django usage patterns
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64

Disable problematic commands in production

rename-command FLUSHDB "" rename-command FLUSHALL "" rename-command DEBUG ""

Enable keyspace notifications for cache invalidation

notify-keyspace-events Ex

Set up Redis monitoring

Configure Redis to log performance metrics and set up basic monitoring.

# Logging configuration
loglevel notice
logfile /var/log/redis/redis-server.log
syslog-enabled yes
syslog-ident redis

Slow log configuration

slowlog-log-slower-than 10000 slowlog-max-len 128

Client output buffer limits

client-output-buffer-limit normal 0 0 0 client-output-buffer-limit slave 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60

Restart Redis with new configuration

Apply the Redis configuration changes by restarting the service.

sudo systemctl restart redis-server
sudo systemctl status redis-server

Test Django Redis integration

Create a Django management command to test caching functionality.

from django.core.management.base import BaseCommand
from django.core.cache import cache
from django.contrib.sessions.models import Session
import time

class Command(BaseCommand):
    help = 'Test Redis caching and session storage'

    def handle(self, *args, **options):
        # Test caching
        cache_key = 'test_key'
        cache_value = 'Hello Redis!'
        
        # Set cache value
        cache.set(cache_key, cache_value, 60)
        
        # Get cache value
        result = cache.get(cache_key)
        
        if result == cache_value:
            self.stdout.write(
                self.style.SUCCESS('Cache test passed: %s' % result)
            )
        else:
            self.stdout.write(
                self.style.ERROR('Cache test failed')
            )
        
        # Test cache performance
        start_time = time.time()
        for i in range(1000):
            cache.set(f'perf_test_{i}', f'value_{i}', 60)
        set_time = time.time() - start_time
        
        start_time = time.time()
        for i in range(1000):
            cache.get(f'perf_test_{i}')
        get_time = time.time() - start_time
        
        self.stdout.write(
            f'Performance: 1000 SETs in {set_time:.3f}s, 1000 GETs in {get_time:.3f}s'
        )

Add template fragment caching

Implement template-level caching for expensive template operations.

{% load cache %}




    My Django App
    {% cache 300 sidebar request.user.id %}
    
    {% endcache %}


    {% cache 600 main_content %}
    
{{ content }}
{% endcache %}

Configure cache invalidation

Set up Django signals to automatically invalidate cache when models change.

from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django.core.cache import cache
from django.core.cache.utils import make_template_fragment_key
from .models import Article

@receiver([post_save, post_delete], sender=Article)
def invalidate_article_cache(sender, instance, **kwargs):
    # Invalidate specific cache keys
    cache_keys = [
        f'article_{instance.id}',
        'article_list',
        'latest_articles',
    ]
    
    cache.delete_many(cache_keys)
    
    # Invalidate template fragment cache
    fragment_key = make_template_fragment_key('article_detail', [instance.id])
    cache.delete(fragment_key)
    
    # Invalidate pattern-based keys
    cache.delete_pattern('article_*')

Verify your setup

Test that Redis is properly integrated with Django for both caching and sessions.

# Check Redis is running
sudo systemctl status redis-server
redis-cli ping

Test Django cache integration

python manage.py test_cache

Check Redis memory usage

redis-cli info memory

Monitor Redis operations

redis-cli monitor

Test session storage by logging into your Django application and checking Redis:

# Check session keys in Redis
redis-cli keys "session"

View Django cache statistics

python manage.py shell >>> from django.core.cache import cache >>> cache.get_stats()

Performance optimization

Enable Redis persistence tuning

Configure Redis persistence for session data while optimizing for performance.

# Optimize RDB saves
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb

Disable AOF for cache-only data (enable for sessions)

appendonly yes appendfilename "appendonly.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb

Configure connection pooling

Optimize Django Redis connections for high-traffic applications.

CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'PASSWORD': 'your_secure_redis_password',
            'CONNECTION_POOL_KWARGS': {
                'max_connections': 100,
                'retry_on_timeout': True,
                'socket_keepalive': True,
                'socket_keepalive_options': {
                    'TCP_KEEPIDLE': 1,
                    'TCP_KEEPINTVL': 3,
                    'TCP_KEEPCNT': 5,
                },
            },
            'COMPRESSOR': 'django_redis.compressors.zlib.ZlibCompressor',
            'IGNORE_EXCEPTIONS': True,
        },
        'TIMEOUT': 300,
    }
}

Enable connection pooling globally

DJANGO_REDIS_CONNECTION_FACTORY = 'django_redis.pool.ConnectionFactory'

Security hardening

Secure Redis access

Implement additional security measures for Redis in production.

# Network security
bind 127.0.0.1
protected-mode yes
port 6379

Authentication

requirepass your_very_secure_redis_password_here

Disable dangerous commands

rename-command FLUSHDB "" rename-command FLUSHALL "" rename-command EVAL "" rename-command DEBUG "" rename-command CONFIG "CONFIG_b835c3b4c1e7f7ad8c7b0f0e8b8e4d9b"

Resource limits

tcp-backlog 511 timeout 300 tcp-keepalive 300 maxclients 10000

Set up Redis firewall rules

Configure firewall to restrict Redis access to Django application only.

# Allow Redis only from localhost
sudo ufw deny 6379
sudo ufw allow from 127.0.0.1 to any port 6379
# Block external Redis access
sudo firewall-cmd --permanent --remove-service=redis
sudo firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=127.0.0.1 port port=6379 protocol=tcp accept"
sudo firewall-cmd --reload

Common issues

SymptomCauseFix
Connection refused errorsRedis not running or wrong portsudo systemctl start redis-server and check /etc/redis/redis.conf
Authentication errorsPassword mismatchVerify Redis password in settings matches /etc/redis/redis.conf
Cache misses under loadMemory eviction policyIncrease maxmemory or check maxmemory-policy setting
Slow cache operationsNetwork latency or memory swappingCheck Redis slow log: redis-cli slowlog get 10
Sessions not persistingRedis persistence disabledEnable RDB or AOF persistence in redis.conf
High memory usageNo expiration on cache keysSet TIMEOUT values in Django cache config
Never use chmod 777. If you encounter permission issues with Redis logs or data files, fix ownership with chown redis:redis and use chmod 644 for files, chmod 755 for directories.

Next steps

Running this in production?

Want this handled for you? Setting this up once is straightforward. Keeping it patched, monitored, backed up and performant across environments is the harder part. See how we run infrastructure like this for European teams.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle infrastructure performance optimization for businesses that depend on uptime. From initial setup to ongoing operations.