skip to content

In Django, which session engines can SESSION_ENGINE select, which is the default, and how do they differ?

level: middleimportance: must knowfreq 55%

answer

  1. five modules under contrib.sessions.backends
  2. the default needs a table
  3. cache alone is lossy
  4. write-through beats cache-only

basics

~10 s

Django's SESSION_ENGINE selects db (the default, a django_session table), cache, cached_db (database with a write-through cache), file, or signed_cookies (data in a signed cookie); they differ in durability, speed, fleet-sharing and revocability.

solid answer

~40 s

`SESSION_ENGINE` is a dotted path to a module with a `SessionStore`; the default is `django.contrib.sessions.backends.db`, which stores rows in `django_session`. `cache` keeps data only in the cache named by `SESSION_CACHE_ALIAS`, so eviction or a restart logs people out. `cached_db` writes to the database and then the cache and reads from the cache with a database fallback — the usual production choice. `file` writes files under `SESSION_FILE_PATH`, local to one host. `signed_cookies` puts the signed, unencrypted session in the cookie itself, so nothing server-side can revoke it. All share the same API and are serialized with `JSONSerializer` by default; `db`, `cached_db` and `file` need `manage.py clearsessions` to purge expired sessions.

code

python · 15 lines
python
# settings.py
INSTALLED_APPS = [
    # ...
    "django.contrib.sessions",
]

SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
SESSION_CACHE_ALIAS = "default"  # the default alias; point at a shared cache

CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.redis.RedisCache",
        "LOCATION": "redis://cache.internal:6379/1",
    }
}

go deeper

for a junior

Know that the session cookie holds only an ID for most engines, and that the default engine stores data in the database table django_session.

for a middle

Name all five engines with their SESSION_ENGINE paths, explain cached_db's write-through order and fallback, and know clearsessions and which engines need it.

for a senior

Choose an engine for a real deployment: durability of baskets and logins, shared cache sizing via SESSION_CACHE_ALIAS, and revocation needs that rule out signed cookies.

for a principal

Treat session storage as a dependency with a failure budget: what a cache loss costs in re-logins and how the engine choice couples the web tier to the database.

## What SESSION_ENGINE chooses Django's session framework (`django.contrib.sessions`) gives every request a dictionary-like `request.session`. The browser only carries an identifier, in a cookie named by `SESSION_COOKIE_NAME` (default `"sessionid"`); the **engine** decides where the data behind that identifier lives. You choose it with the `SESSION_ENGINE` setting, a dotted path to a module that provides a `SessionStore` class. `SessionMiddleware` imports that module once and builds a `SessionStore(session_key)` for each request. Django ships five engines under `django.contrib.sessions.backends`: | `SESSION_ENGINE` value | Where data lives | Survives a cache or worker restart | `clearsessions` | |---|---|---|---| | `...backends.db` (**default**) | `django_session` table | Yes | Deletes expired rows | | `...backends.cache` | The cache named by `SESSION_CACHE_ALIAS` (default `"default"`) | No | No-op; the cache expires entries | | `...backends.cached_db` | Database, with a write-through cache in front | Yes (reads fall back to the DB) | Deletes expired rows | | `...backends.file` | Files under `SESSION_FILE_PATH` (default: the system temp directory) | Yes, on that host | Deletes expired files | | `...backends.signed_cookies` | The cookie itself, signed with `SECRET_KEY` | Nothing server-side to lose | No-op | ## The engines one by one - **`db`** is the default in `django/conf/global_settings.py`. It needs `django.contrib.sessions` in `INSTALLED_APPS` and its migration applied. The first access to the session in a request costs a query, and every save costs a write. - **`cache`** keeps data only in the cache. It is fast but lossy: eviction or a cache restart logs users out. The Django docs say to use it only with the Memcached or Redis cache backends; the local-memory cache is per-process and not multi-process safe. - **`cached_db`** is the usual production compromise. Writes go to the database and then the cache; reads use the cache and fall back to the database when the entry was evicted. Since Django 5.1 a failed cache write is caught and logged through the `django.contrib.sessions` logger instead of failing the request. - **`file`** writes one file per session, named with the session cookie name as a prefix. The files are local to one machine unless the directory is shared. - **`signed_cookies`** stores the serialized session in the cookie, signed (not encrypted) with Django's signing tools. There is no server-side record, so there is nothing to revoke on logout, and the cookie is limited by the browser's per-cookie size limit. ## What stays the same across engines Whatever the engine, the session API and its behaviour around saving are identical: 1. `SessionMiddleware.process_request` creates the store from the cookie value. 2. Your view reads and writes `request.session`; data is loaded lazily on first access. 3. `SessionMiddleware.process_response` saves only if the session was **modified** or `SESSION_SAVE_EVERY_REQUEST` is `True`, it is not empty, and the response status is below 500. It then sets the cookie using the `SESSION_COOKIE_*` settings. The data is serialized with `SESSION_SERIALIZER`, which defaults to `django.contrib.sessions.serializers.JSONSerializer`, so values must be JSON-serializable. (The old `PickleSerializer` was removed in Django 5.0.) Server-side engines also sign the stored payload, so rotating `SECRET_KEY` without listing the old key in `SECRET_KEY_FALLBACKS` makes existing sessions unreadable. ## Choosing one - A single server, modest traffic: keep `db`. - Several app servers and frequent session reads: `cached_db` with a shared cache. - Throwaway state where losing it is acceptable: `cache`, with a real shared cache backend. - A stateless deployment with tiny, non-sensitive session data and no need to kill sessions server-side: `signed_cookies`. - `file` mainly for development or a single host. ## Common misconceptions - **"The cookie holds the session."** Only for `signed_cookies`; every other engine sends just a random key and keeps the data server-side. - **"`cache` falls back to the database."** It does not; that is precisely what `cached_db` adds. On a cache miss the `cache` engine treats the session as new. - **"Any cache backend will do."** With no `CACHES` setting Django uses the local-memory backend, which is private to each process. - **"Sessions are saved on every request."** They are saved when modified, unless `SESSION_SAVE_EVERY_REQUEST` is `True`. - **"Signed means encrypted."** A signed cookie is tamper-evident but readable. ## Housekeeping Expired sessions are not deleted automatically by the `db` and `file` engines. `manage.py clearsessions` calls the engine's `clear_expired()`; run it on a schedule. For `cache` and `signed_cookies` the call is a no-op, and a custom engine that does not implement it makes the command fail with a `CommandError`.

  • Why does the django_session table keep growing even though sessions expire?
    The `db` and `cached_db` engines check expiry when a session is loaded but never delete old rows on their own. `manage.py clearsessions` calls the engine's `clear_expired()`, which deletes rows whose `expire_date` has passed. Run it on a schedule; for `cache` and `signed_cookies` it is a no-op.
  • In Django's cached_db engine, what happens when writing to the cache fails?
    The database write has already happened, because `cached_db` writes the database first. Since Django 5.1 the cache exception is caught and logged through the `django.contrib.sessions` logger instead of failing the request, and later reads fall back to the database.

saying these in an interview costs you the question

  • Django's default session engine is the cache
  • The cache engine also persists sessions to the database
  • Signed cookie sessions are encrypted so users cannot read them
  • Expired database sessions are deleted automatically
  • Session data is pickled by default