Skip to content

fix: RuntimeError fallback and stampede protection - #31

Open
emiliano-go wants to merge 1 commit into
redis:mainfrom
emiliano-go:fix/resilience-performance
Open

emiliano-go wants to merge 1 commit into
redis:mainfrom
emiliano-go:fix/resilience-performance

Conversation

@emiliano-go

Copy link
Copy Markdown
Contributor

Changes

Bug: _store_cache_entry crashes with unhandled RuntimeError (500)

When CachePending.redis is None, the middleware falls back to
_get_pool_state(app).get_async_client(). If no lifespan is registered
this raises RuntimeError, which was not caught by the existing
except (RedisError, OSError) handler, crashing the response with a 500.

Fix: Added RuntimeError to the caught exception types. The error is
logged as a warning and the response is delivered without caching (graceful
degradation).

Bug: Thundering herd / cache stampede

When many concurrent requests arrive just before a cached entry expires, all
of them miss and recompute simultaneously, overwhelming the origin.

Fix: Added stampede_protection: bool = False to cache(). When
enabled and the remaining TTL drops below 10% of the original TTL, a hit
is probabilistically promoted to a miss with probability
1 - (remaining_ttl / threshold). Only a fraction of concurrent requests
recompute, keeping origin load manageable.

@tishun
tishun self-requested a review August 19, 2026 12:41
@tishun tishun added the needs-triage The team needs to go through the provided information and analyse it label Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-triage The team needs to go through the provided information and analyse it

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants