Belajar Django - Cache & Sessions
Episode 12 of 27

Belajar Django - Cache & Sessions

Mengaktifkan framework cache Django dengan backend LocMem, Redis, dan Memcached, menerapkan per-view dan per-template caching, lalu memindahkan session ke Redis agar login cepat dan aplikasi siap scale horizontal.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah API berdiri di episode 11, pertanyaan berikutnya adalah performa: halaman blog di-render ulang untuk setiap request padahal isinya jarang berubah. Di episode ini kita menerapkan Cache & Sessions — dua mekanisme yang membuat aplikasi terasa instan dan tetap scalable.

Mengapa topik ini penting? Caching adalah strategi performa dengan rasio usaha-hasil terbaik: sekali render, dibaca ribuan kali tanpa menyentuh database. Session adalah kebalikannya — data sementara per-user yang harus tetap cepat dan bisa dibagikan antar server saat aplikasi di-scale horizontal (episode 24). Keduanya sering menggunakan infrastruktur yang sama: Redis.

Framework Cache Django

Django punya sistem cache terpadu dengan banyak backend. Pilihannya, dari yang paling sederhana:

BackendKinerjaPersistensiCocok untuk
LocMemCacheSedangPer-proses, hilang saat restartDevelopment, single worker
DatabaseCacheRendahYa (di DB)Lab tanpa infra tambahan
FileBasedCacheRendahYa (file)Sistem tanpa memori proses
MemcachedCacheTinggiTidakProduksi klasik
RedisCacheTinggiOpsional (persist)Produksi modern + session/celery

Konfigurasi Redis di settings.py:

Pythonsettings.py - Redis cache
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.redis.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "TIMEOUT": 300,
        "KEY_PREFIX": "devblog",
    }
}

KEY_PREFIX memisahkan key cache antar aplikasi di Redis yang sama. TIMEOUT default 300 detik — jangan set terlalu lama jika data berubah cepat.

Note

LocMemCache sempurna untuk development karena tanpa server tambahan, tetapi berbahaya di produksi: ia disimpan per-proses worker, jadi cache worker A tidak terlihat worker B — hasilnya cache yang tidak konsisten. Saat kalian menjalankan beberapa worker Gunicorn (episode 23), pastikan backend sudah pindah ke Redis.

Menggunakan Cache di Kode

Pola paling umum: cache-aside. Baca dari cache; jika miss, ambil dari database dan isi cache:

Pythonblog/views.py - cache-aside
from django.core.cache import cache
 
def category_posts(category_slug, timeout=300):
    key = f"category:{category_slug}:post_ids"
    ids = cache.get(key)
    if ids is None:
        ids = list(
            Post.objects.filter(category__slug=category_slug, status="published")
            .values_list("id", flat=True)
        )
        cache.set(key, ids, timeout)
    return Post.objects.filter(id__in=ids).select_related("author")

cache.set(key, value, timeout) dengan None artinya default. Perhatikan kita cache daftar id (ringan), bukan objek utuh — objek tetap diambil via query saat dibutuhkan, menghindari cache yang menyimpan referensi stale.

Per-View Caching

Untuk halaman yang identik untuk semua user, cache seluruh respons view:

Pythonblog/views.py - cache_page
from django.views.decorators.cache import cache_page
 
@cache_page(60 * 15)  # 15 menit
def popular_posts(request):
    ...

cache_page men-cache HttpResponse lengkap selama 15 menit. Hati-hati: view yang menampilkan data per-user (nama user, keranjang) tidak boleh di-cache per-halaman tanpa Vary header yang benar.

Per-Template Caching

Jika hanya sebagian halaman yang mahal dirender (misal sidebar "post populer"), cache potongan template:

Pythontemplates/partials/sidebar.html
{% load cache %}
 
{% cache 600 popular_posts %}
{% for post in popular_posts %}
    <li><a href="{% url 'blog:post_detail' post.pk %}">{{ post.title }}</a></li>
{% endfor %}
{% endcache %}

Sintaks {% cache timeout key %} men-cache blok template berdasarkan key. Untuk cache per-user, tambahkan fragment key unik:

PythonCache per-user
{% cache 60 sidebar user.id %}
...
{% endcache %}

Cache API untuk Query

Untuk query yang berat dan jarang berubah, kombinasi cache + annotate:

PythonCaching query agregat
from django.core.cache import cache
 
def get_stats():
    stats = cache.get("blog:stats")
    if stats is None:
        stats = {
            "posts": Post.objects.count(),
            "comments": Comment.objects.count(),
            "authors": User.objects.filter(is_active=True).count(),
        }
        cache.set("blog:stats", stats, 600)
    return stats

Ini menyelamatkan tiga query COUNT per request. Ingat prinsip dari episode 5: jangan taruh query mahal di context processor — taruh di cache.

Sessions: dari Database ke Redis

Sesi login (episode 10) disimpan di database by default (django.contrib.sessions.backends.db). Saat traffic naik, tabel django_session jadi beban, dan aplikasi multi-worker butuh sesi yang shared — bukan tersimpan per-worker. Pindahkan ke Redis:

Pythonsettings.py - session Redis
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"

django.contrib.sessions.backends.cache menyimpan session langsung di backend cache (default = Redis dari konfigurasi di atas). Hasilnya:

  • Session baca/tulis jauh lebih cepat daripada query DB.
  • Semua worker berbagi session yang sama — syarat mutlak scale horizontal di episode 24.
  • Ekspirasi otomatis mengikuti SESSION_COOKIE_AGE dan Redis TTL.

Warning

Hati-hati dengan backends.cache: jika Redis direstart dan tanpa persistensi, semua session hilang — pengguna ter-logout massal. Untuk produksi, aktifkan Redis persistence (RDB/AOF) atau pertimbangkan cache_db backend yang menulis ke cache dan database sekaligus. Ini juga alasan SESSION_COOKIE_AGE sebaiknya tetap wajar (misal 2 minggu), bukan setahun.

Atur kebijakan session di settings:

Pythonsettings.py - kebijakan session
SESSION_COOKIE_AGE = 60 * 60 * 24 * 14  # 14 hari
SESSION_COOKIE_HTTPONLY = True          # default: mencegah akses JS
SESSION_COOKIE_SECURE = False           # jadi True di produksi HTTPS (episode 18)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False

SESSION_COOKIE_HTTPONLY = True (default Django) membuat cookie session tidak bisa dibaca JavaScript — pertahanan penting melawan XSS (episode 18). SESSION_COOKIE_SECURE baru diaktifkan saat produksi ber-HTTPS.

Verifikasi

Uji cache dan session berjalan:

Verifikasi cache Redis
python manage.py shell -c "
from django.core.cache import cache
cache.set('probe', 42, 60)
print(cache.get('probe'))
"
redis-cli ping
redis-cli -n 1 keys 'devblog:*' | head

redis-cli ping harus menjawab PONG. Key devblog:* di DB 1 Redis berisi entri cache — bukti bahwa Django benar-benar memakai Redis, bukan backend lain.

Penutup

Inti yang harus dibawa pulang:

  • Framework cache Django mendukung banyak backend; Redis pilihan modern untuk produksi.
  • Pola cache-aside (get → miss → query → set) untuk data yang jarang berubah.
  • @cache_page untuk seluruh halaman; {% cache %} untuk potongan template.
  • Jangan cache data per-user tanpa key unik.
  • Session di Redis (backends.cache) = cepat + shared antar worker — syarat scale horizontal.
  • Aktifkan persistence Redis agar session tidak hilang saat restart.

Di episode 13 selanjutnya kita memindahkan pekerjaan berat ke latar belakang: Background Tasks & Celery — Celery dengan Redis, tasks, beat scheduler, dan result backend untuk async email, laporan, dan job terjadwal. Sampai jumpa di episode 13!

Belajar Django - Cache & Sessions | Belajar Django