Dependency Invalidation
Cachecore's dependency system lets you tag cached responses with the data they depend on. When that data changes, invalidate the tag and all associated cache entries (L1 and L2) are deleted.
The problem
If you cache "Summarise contract #123" and the contract is later updated, the stale summary continues to be served until TTL expiry. TTL-based expiry alone is not sufficient for data-sensitive workloads.
How it works
- Tag at request time. Declare dependencies when making a cached request:
with cc.request_context(deps=[Dep("doc:contract-123", hash="v1")]):
response = await openai.chat.completions.create(
model="gpt-5.4-mini",
messages=[{"role": "user", "content": "Summarise contract #123"}],
)
-
Cachecore stores the dep alongside the entry. The
dep_idandexpected_hashare written to a Redis set (cc:dep:keys:{dep_id}) that tracks which cache keys depend on this resource. -
Invalidate when data changes. Call
invalidatewith the dep ID and a new hash:
result = await cc.invalidate("doc:contract-123", new_hash="v2")
- Cachecore deletes all tagged entries. Both L1 (
cc:l1:...) and L2 (vec:...) entries referencing this dep are removed from Redis.
Multiple dependencies per request
A single cache entry can declare multiple deps:
with cc.request_context(deps=[
Dep("doc:contract-123"),
Dep("user:tenant-456"),
]):
response = await openai.chat.completions.create(...)
The entry is invalidated if any of its deps is invalidated.
Bulk invalidation
results = await cc.invalidate_many(
dep_ids=["table:products", "table:prices"],
new_hash="2024-03-15",
)
for r in results:
print(r.dep_id, "ok" if r.ok else r.error)
Via HTTP:
curl -X POST https://api.cachecore.it/v1/invalidate \
-H "Authorization: Bearer cc_live_xxxxx.eyJ..." \
-d '{"dep_id": "table:products", "new_hash": "2024-03-15"}'
Expected hash validation
The hash parameter in Dep("doc:contract-123", hash="v1") is the data version at cache-write time. On subsequent cache lookups, if the current hash for that dep has been updated (via /v1/invalidate), the cached entry is rejected even before TTL expiry.
This enables version-aware caching:
Dep("doc:contract-123", hash=document.version)
# After an update:
await cc.invalidate("doc:contract-123", new_hash=document.new_version)
Automatic policy-version dep
Cachecore appends a cc:policy-version dep to every cache entry automatically. This allows global cache invalidation by rolling the policy version. See Namespaces for details.
Production patterns
See Invalidation Patterns for recipes covering webhooks, event-driven invalidation, batch updates, and bypass for write operations.