Skip to main content

Caching

Ryx includes a pluggable query cache that stores query results and auto-invalidates on writes.

Quick Setupโ€‹

import ryx

# Enable in-memory LRU cache
ryx.configure_cache(ttl=300, max_size=1000) # 5 min TTL, 1000 entries

Cached Queriesโ€‹

# First call โ€” executes query, caches result
posts = await Post.objects.filter(active=True).cache()

# Second call โ€” returns cached result (no DB query)
posts = await Post.objects.filter(active=True).cache()

# After a write โ€” cache is invalidated
await Post.objects.create(title="New post", slug="new")

# Next call โ€” executes query again, caches new result
posts = await Post.objects.filter(active=True).cache()

How It Worksโ€‹

  1. Cache key โ€” SHA-256 hash of the SQL query + bound values
  2. Storage โ€” Pluggable via AbstractCache protocol
  3. Invalidation โ€” Auto-invalidated on post_save and post_delete signals

Custom Cache Backendโ€‹

from ryx.cache import AbstractCache

class RedisCache(AbstractCache):
def __init__(self, redis_client):
self.redis = redis_client

async def get(self, key: str):
data = await self.redis.get(key)
return json.loads(data) if data else None

async def set(self, key: str, value, ttl: int):
await self.redis.setex(key, ttl, json.dumps(value))

async def delete(self, key: str):
await self.redis.delete(key)

async def clear(self):
await self.redis.flushdb()

ryx.configure_cache(backend=RedisCache(redis_client), ttl=300)

Manual Invalidationโ€‹

import ryx.cache as cache

# Invalidate a specific cache key
await cache.invalidate("my_cache_key")

# Invalidate all cache entries for a model
await cache.invalidate_model(Post)

# Invalidate the entire cache
await cache.invalidate_all()

Memory Cache Optionsโ€‹

ryx.configure_cache(
ttl=300, # Time-to-live in seconds
max_size=1000, # Maximum number of cached queries
)

# Access the cache backend directly
backend = ryx.get_cache() # โ†’ Optional[AbstractCache]

When to Cacheโ€‹

  • Expensive queries โ€” Complex aggregations, large result sets
  • Frequently read data โ€” Configuration, categories, tags
  • Read-heavy endpoints โ€” API responses that rarely change

When NOT to Cacheโ€‹

  • Write-heavy data โ€” Cache invalidation overhead
  • Real-time requirements โ€” Stale data is unacceptable
  • Unique queries โ€” Every query has different parameters

Cache Key Mechanismโ€‹

Cache keys are generated as a SHA-256 hash of:

  • Model name
  • SQL query string
  • Bound parameter values

The same query with the same parameters always produces the same cache key.

Full API Referenceโ€‹

FunctionDescription
configure_cache(backend, auto_invalidate=True)Set the cache backend
get_cache()Get the current cache backend
make_cache_key(model_name, sql, values)Build a cache key manually
invalidate(key)Remove a specific cache entry
invalidate_model(model)Remove all cache entries for a model
invalidate_all()Clear the entire cache
ClassDescription
AbstractCachePluggable backend protocol
MemoryCache(max_size=1000, ttl=300)Built-in LRU in-process cache

Next Stepsโ€‹

โ†’ Custom Lookups โ€” Extend the query API