Disk Persistence
async-cache supports optional disk-backed storage so your cache survives process restarts. This is critical for expensive ML inference caches, web scraper results, or any data that takes minutes to warm up.
No new dependencies — uses Python’s built-in pickle module.
Quick Start
from cache import AsyncCache, DiskBackend
backup = DiskBackend("/tmp/my_app_cache.pkl")
cache = AsyncCache(maxsize=10000, default_ttl=3600, backup=backup)
# Use normally — cache loads from disk on init
value = await cache.get("key", loader=lambda: expensive_computation())
# On shutdown, persist to disk
cache.save_to_backup()
How It Works
On init:
AsyncCachecallsbackup.load()to warm up from diskDuring runtime: All operations are in-memory (same performance)
On shutdown: Call
save_to_backup()to persist current entriesTTL preservation: Remaining TTL is saved and restored correctly
import atexit
from cache import AsyncCache, DiskBackend
backup = DiskBackend("/var/cache/myapp/cache.pkl")
cache = AsyncCache(maxsize=5000, default_ttl=600, backup=backup)
# Auto-save on shutdown
atexit.register(cache.save_to_backup)
With Decorators
from cache import AsyncLRU, AsyncTTL, DiskBackend
lru_backup = DiskBackend("/tmp/product_cache.pkl")
@AsyncLRU(maxsize=1000, backup=lru_backup)
async def get_product(product_id: int):
return await db.query_product(product_id)
# Save on shutdown
get_product.save_to_backup()
# Reload from disk manually
get_product.load_from_backup()
With AgentCache
from agent_cache import AgentCache
from cache import DiskBackend
@AgentCache(resource="embeddings", scope="global", backup=DiskBackend("/tmp/embeddings.pkl"))
async def get_embedding(text):
return await ml_model.embed(text)
Custom Backends
To build a Redis or Memcached backend, subclass CacheBackend:
from cache.backend import CacheBackend
class RedisBackend(CacheBackend):
def __init__(self, redis_url):
self.redis = redis.from_url(redis_url)
def load(self):
# Return {key: (value, monotonic_expiration_or_None)}
...
def save(self, data):
# data is {key: (value, ttl_remaining_seconds_or_None)}
...
def clear(self):
self.redis.flushdb()
The CacheBackend ABC requires three methods:
Method |
Description |
|---|---|
|
Return |
|
Persist |
|
Remove all persisted data. |
DiskBackend Details
Atomic writes: Uses write-to-temp +
os.replace()to prevent corruptionAuto-creates directories: Parent directories are created if missing
Corrupt file handling: Returns empty dict on unpickling errors
Thread-safe: Internal locking for concurrent save/load
Timestamp tracking: Elapsed time between save and load is subtracted from TTLs