ADR-002: Function Result Caching in Django’s Cache Framework
Status
Accepted
Context
Expensive work, such as a database query or a call to a third-party api, is
often repeated with the same arguments. Projects tend to hand-roll
cache.get() and cache.set() around it, each with its own key format,
invalidation and handling of None.
Decision
The package offers one decorator, @cache_results, that caches a function’s
result by its arguments, in a cache of Django’s cache framework, and gives the
function an invalidate() for the same arguments. None is cached like any
other result. It caches function results, not objects: there is no model or
queryset caching.
Alternatives Considered
Object or queryset caching, such as django-cacheops or django-cachalot, which patch the ORM.
An in-process cache such as
functools.lru_cache, which is neither shared between servers nor survives a restart.A cache client of its own, rather than Django’s cache framework.
Consequences
Positive:
Works with every Django cache backend, and shares results across processes and servers with a shared cache such as Redis.
One key format and one way to invalidate, instead of one per call site.
Negative:
Every call serializes and hashes its arguments and makes a round trip to the cache, so it doesn’t suit cheap, short-lived results.
The caller decides what to cache and when to invalidate: nothing is invalidated automatically when data changes.