---
title: "Keep the app working when the cache is · Agent Wranglers"
url: https://agentwranglers.se/playbook/scaling/caching/survive-cache-loss
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Keep the app working when the cache is gone

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Caching](https://agentwranglers.se/playbook/scaling/caching.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

- ID: SCL-15
- Level: Required
- Chapter: [Caching](https://agentwranglers.se/playbook/scaling/caching)
- Rule: Treat every cache call as optional. On a cache error or timeout, read from the source, so the service stays up when the cache is down or empty.
- Risk: The app down or unusable
- How: Give cache calls a short time limit, such as 50 ms, far below the request's own limit from [Set timeouts on every call](https://agentwranglers.se/playbook/api-design/reliability/timeouts). Catch cache errors, log them and fall back to the source of truth. An empty cache after a restart sends every read to the database at once. Test that the database survives this, or refuse the excess as [Turn work away before overload](https://agentwranglers.se/playbook/operations/capacity-and-cost/load-shedding) does. The Google SRE book warns that a service that copes only with a warm cache is at higher risk of outage.
- Check: Stop the cache server on staging while the load test runs at the planned peak. The error rate stays under 1%. After the cache returns, response times are back to normal within 5 minutes.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
const CACHE_TIMEOUT_MS = 50;

export async function readThrough(cache, key, load) {
  try {
    const hit = await Promise.race([
      cache.get(key),
      new Promise((_, reject) => setTimeout(() => reject(new Error('cache timeout')), CACHE_TIMEOUT_MS)),
    ]);
    if (hit !== null) return JSON.parse(hit);
  } catch (error) {
    log.warn({ key, error: error.message }, 'cache unavailable, reading source');
  }
  return load();
}
```

### Python example

```python
import json
import logging

import redis

CACHE_TIMEOUT_SECONDS = 0.05
cache = redis.Redis(host="cache.internal.example.com", socket_timeout=CACHE_TIMEOUT_SECONDS)

def read_through(key: str, load):
    try:
        hit = cache.get(key)
        if hit is not None:
            return json.loads(hit)
    except redis.RedisError as error:
        logging.warning("cache unavailable, reading source: %s", error)
    return load()
```

## Sources

- [Google SRE book, Addressing Cascading Failures](https://sre.google/sre-book/addressing-cascading-failures/)

## Related rules

- [Set timeouts on every call](https://agentwranglers.se/playbook/api-design/reliability/timeouts) in API design
- [Turn work away before overload](https://agentwranglers.se/playbook/operations/capacity-and-cost/load-shedding) in Operations

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/scaling/caching/survive-cache-loss">Agent Wranglers scaling playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Cap the cache server's memory and choose its eviction](https://agentwranglers.se/playbook/scaling/caching/cache-memory-and-eviction)
- Next: [Decide how stale a cache may be](https://agentwranglers.se/playbook/scaling/caching/cache-freshness)
- [Caching](https://agentwranglers.se/playbook/scaling/caching)
