Configuration Reference¶
Reference for all django-cachex configuration options.
Basic Configuration¶
CACHES = {
"default": {
"BACKEND": "django_cachex.cache.ValkeyCache", # or RedisCache
"LOCATION": "valkey://127.0.0.1:6379/1",
"TIMEOUT": 300, # Default timeout in seconds
"KEY_PREFIX": "myapp", # Prefix for all keys
"VERSION": 1, # Key version number
"OPTIONS": {
# See options below
},
}
}
Backend Classes¶
All backends live in django_cachex.cache.
Valkey / Redis (Python driver)¶
| Backend | Description |
|---|---|
ValkeyCache |
Standard Valkey connection |
RedisCache |
Standard Redis connection |
ValkeySentinelCache |
Valkey Sentinel high availability |
RedisSentinelCache |
Redis Sentinel high availability |
ValkeyClusterCache |
Valkey Cluster sharding |
RedisClusterCache |
Redis Cluster sharding |
Valkey / Redis (Rust driver)¶
Experimental
The Rust driver is experimental: interfaces and behavior may change, and it has seen less production testing than the redis-py/valkey-py backends.
Nearly the same wire-level feature set as the Python driver, dispatched through the optional django-cachex-redis-rs extension (PyO3 + tokio + redis-rs). slowlog_get and slowlog_len are the exceptions and raise NotSupportedError. Sync and async share one tokio runtime, so async paths skip the asgiref threadpool round-trip. Install via the redis-rs extra.
| Backend | Description |
|---|---|
RedisRsCache |
Standard connection (Valkey or Redis, protocol-compatible) |
RedisRsSentinelCache |
Sentinel high availability |
RedisRsClusterCache |
Cluster sharding |
Valkey-Glide¶
Experimental
The valkey-glide adapter is experimental: interfaces and behavior may change, and it has seen less production testing than the redis-py/valkey-py backends.
Valkey's official client library, bundled as valkey-glide. Async-first; cachex wraps the async client transparently. Install via the valkey-glide extra.
| Backend | Description |
|---|---|
ValkeyGlideCache |
Standard Valkey connection via valkey-glide |
ValkeyGlideClusterCache |
Cluster sharding via valkey-glide |
CACHES = {
"default": {
"BACKEND": "django_cachex.cache.ValkeyGlideCache",
"LOCATION": "valkey://127.0.0.1:6379/0",
}
}
See the upstream valkey-glide docs for client-specific tuning. Sentinel is not exposed (valkey-glide itself does not ship a Sentinel client).
Local backends¶
| Backend | Description |
|---|---|
LocMemCache |
Drop-in replacement for Django's LocMemCache with data-structure ops, TTL helpers, and admin support |
DatabaseCache |
Drop-in replacement for Django's DatabaseCache with the same extensions |
Composite backends¶
| Backend | Description |
|---|---|
StreamCache |
In-memory store synchronized across pods via a Redis Stream consumer |
TieredCache |
Composes two existing CACHES entries as L1/L2 with TTL propagation |
Valkey and Redis Compatibility
Valkey and Redis are protocol-compatible, so either backend works with either server. Valkey is recommended as it remains fully open source.
LOCATION¶
Server URL(s):
# Single server (Valkey)
"LOCATION": "valkey://127.0.0.1:6379/1"
# Single server (Redis)
"LOCATION": "redis://127.0.0.1:6379/1"
# With authentication
"LOCATION": "valkey://user:password@127.0.0.1:6379/1"
# SSL/TLS
"LOCATION": "valkeys://127.0.0.1:6379/1" # or rediss://
# Unix socket
"LOCATION": "unix:///path/to/socket?db=1"
# Multiple servers (read replicas)
"LOCATION": [
"valkey://127.0.0.1:6379/1", # Primary (writes)
"valkey://127.0.0.1:6380/1", # Replica (reads)
]
# Or comma/semicolon separated
"LOCATION": "valkey://127.0.0.1:6379/1,valkey://127.0.0.1:6380/1"
OPTIONS Reference¶
Serialization¶
"OPTIONS": {
# Single serializer (string path, class, or instance)
"serializer": "django_cachex.serializers.pickle.PickleSerializer",
# Or with fallback for migration
"serializer": [
"django_cachex.serializers.msgpack.MsgpackSerializer", # Write
"django_cachex.serializers.pickle.PickleSerializer", # Fallback read
],
}
Available serializers:
| Serializer | Description |
|---|---|
django_cachex.serializers.pickle.PickleSerializer |
Python pickle (default) |
django_cachex.serializers.json.JsonSerializer |
JSON via DjangoJSONEncoder |
django_cachex.serializers.msgpack.MsgpackSerializer |
MessagePack (requires msgpack) |
django_cachex.serializers.orjson.OrjsonSerializer |
Rust-backed JSON (requires orjson) |
django_cachex.serializers.ormsgpack.OrmsgpackSerializer |
Rust-backed MessagePack (requires ormsgpack) |
See Serializers for type-compatibility details and benchmarks.
Compression¶
"OPTIONS": {
# Single compressor
"compressor": "django_cachex.compressors.zstd.ZstdCompressor",
# Or with fallback for migration
"compressor": [
"django_cachex.compressors.zstd.ZstdCompressor", # Write
"django_cachex.compressors.zlib.ZlibCompressor", # Fallback read
],
}
Available compressors:
| Compressor | Description |
|---|---|
django_cachex.compressors.zlib.ZlibCompressor |
zlib (stdlib) |
django_cachex.compressors.gzip.GzipCompressor |
gzip (stdlib) |
django_cachex.compressors.lzma.LzmaCompressor |
LZMA (stdlib) |
django_cachex.compressors.zstd.ZstdCompressor |
Zstandard (stdlib on 3.14+) |
django_cachex.compressors.lz4.Lz4Compressor |
LZ4 (requires lz4) |
Compression is only applied to values larger than min_length bytes (default: 256).
Connection Pool¶
"OPTIONS": {
# Custom pool class (use valkey.ConnectionPool for Valkey)
"pool_class": "valkey.ConnectionPool",
"retry_on_timeout": True,
# Socket timeouts
"socket_connect_timeout": 5,
"socket_timeout": 5,
}
Any extra keys you add are forwarded to the underlying pool's from_url(...),
so you can pin driver-specific options (socket_keepalive, health_check_interval,
etc.) the same way.
Parser¶
"OPTIONS": {
# Dotted path or class; defaults to the driver's DefaultParser
"parser_class": "valkey.connection.DefaultParser", # or "redis.connection.DefaultParser"
}
You rarely need to set this. When omitted, the driver's DefaultParser
is used, which resolves to the C-accelerated parser when libvalkey
(Valkey) or hiredis (Redis) is installed and to the pure-Python RESP
parser otherwise. To get the C parser, install the libvalkey or
hiredis extra; no parser_class setting is required.
Cache stampede prevention¶
Probabilistic early recompute (XFetch) to avoid thundering-herd recompute when a hot key expires:
"OPTIONS": {
# Enable with defaults (buffer=60s, beta=1.0, delta=1.0)
"stampede_prevention": True,
# Or tune individually
"stampede_prevention": {
"buffer": 30, # extra TTL added to writes; recompute window inside this buffer
"beta": 1.0, # higher = more aggressive early recompute
"delta": 1.0, # estimated recompute cost (seconds)
},
}
Per-call overrides accept the same shapes via the stampede_prevention= keyword on get/set/add/touch/get_or_set/get_many/set_many, and on their a-prefixed async counterparts. On touch the keyword decides whether the refreshed TTL gets the buffer added back, so it should match what the original write used.
Choosing an adapter¶
The adapter (the layer that talks to the underlying client lib) is
selected by your BACKEND. Each cache class has a fixed adapter:
| Backend | Adapter |
|---|---|
django_cachex.cache.RedisCache |
redis-py |
django_cachex.cache.ValkeyCache |
valkey-py |
django_cachex.cache.RedisRsCache |
Rust driver |
django_cachex.cache.ValkeyGlideCache |
valkey-glide |
django_cachex.cache.ValkeyGlideClusterCache |
valkey-glide |
To use a different adapter, change BACKEND. The matching
*ClusterCache and *SentinelCache classes pick the same
adapter family in cluster/sentinel mode.
Authentication¶
Password in URL¶
Password with Special Characters¶
For passwords with special characters, pass via OPTIONS:
Valkey/Redis ACLs¶
SSL/TLS¶
Basic SSL¶
Self-Signed Certificates¶
"LOCATION": "valkeys://127.0.0.1:6379/1",
"OPTIONS": {
"ssl_cert_reqs": None, # Disable verification
}
Custom Certificates¶
"LOCATION": "valkeys://127.0.0.1:6379/1",
"OPTIONS": {
"ssl_ca_certs": "/path/to/ca.crt",
"ssl_certfile": "/path/to/client.crt",
"ssl_keyfile": "/path/to/client.key",
}
Sentinel Configuration¶
CACHES = {
"default": {
"BACKEND": "django_cachex.cache.RedisSentinelCache",
"LOCATION": "redis://mymaster/0", # Master name
"OPTIONS": {
"sentinels": [
("sentinel1.example.com", 26379),
("sentinel2.example.com", 26379),
("sentinel3.example.com", 26379),
],
"sentinel_kwargs": {
"password": "sentinel-password",
},
},
}
}
Cluster Configuration¶
CACHES = {
"default": {
"BACKEND": "django_cachex.cache.RedisClusterCache",
"LOCATION": "redis://127.0.0.1:7000",
}
}
Timeouts¶
Default Timeout¶
Special Values¶
cache.set("key", "value", timeout=0) # Delete immediately
cache.set("key", "value", timeout=None) # Never expires
Key Configuration¶
Key Prefix¶
Key Version¶
Custom Key Function¶
def my_key_func(key, key_prefix, version):
return f"{key_prefix}:v{version}:{key}"
CACHES = {
"default": {
...
"KEY_FUNCTION": "myapp.cache.my_key_func",
}
}
Reverse Key Function¶
def my_reverse_key_func(key):
return key.split(":", 2)[2]
CACHES = {
"default": {
...
"REVERSE_KEY_FUNCTION": "myapp.cache.my_reverse_key_func",
}
}
The inverse of KEY_FUNCTION: it takes the full internal key and returns the user key. Dotted path or callable, same as KEY_FUNCTION. Reach for it when a custom KEY_FUNCTION makes the default prefix:version: stripping wrong; the default handles a KEY_PREFIX containing colons on its own.
Only reverse_key() consults it, so it changes what keys(), iter_keys(), scan() and the blocking list pops (blpop, brpop) hand back, plus their async counterparts. Stored keys are untouched.
RESP backends only
LocMemCache, DatabaseCache and StreamCache strip the prefix
themselves and ignore REVERSE_KEY_FUNCTION. TieredCache forwards
reverse_key() to its L2 tier, so it belongs on the L2 alias rather
than the tiered one.
Complete Example¶
CACHES = {
"default": {
"BACKEND": "django_cachex.cache.ValkeyCache",
"LOCATION": "valkey://127.0.0.1:6379/1",
"TIMEOUT": 300,
"KEY_PREFIX": "myapp",
"VERSION": 1,
"OPTIONS": {
# Serialization
"serializer": "django_cachex.serializers.pickle.PickleSerializer",
# Compression
"compressor": "django_cachex.compressors.zstd.ZstdCompressor",
# Connection pool
"socket_connect_timeout": 5,
"socket_timeout": 5,
},
}
}