Skip to content

fix: remove permanent cache backend mutation on Redis error - #846

Merged
jakharmonika364 merged 3 commits into
Coder-s-OG-s:mainfrom
ionfwsrijan:fix/issue-843-cache-backend-mutation
Aug 1, 2026
Merged

fix: remove permanent cache backend mutation on Redis error#846
jakharmonika364 merged 3 commits into
Coder-s-OG-s:mainfrom
ionfwsrijan:fix/issue-843-cache-backend-mutation

Conversation

@ionfwsrijan

Copy link
Copy Markdown
Contributor

Description

The IoRedisBackend constructor registers an error handler on the Redis client that permanently replaces the global backend variable with a fresh MemoryBackend on any Redis error. There is no recovery mechanism — once switched, backend is never reset back to Redis. In multi-instance deployments, a transient Redis blip permanently kills distributed rate limiting on that instance.

Changes

  • Removed the backend = new MemoryBackend() reassignment from the ioredis error event handler
  • The error handler now only logs a warning instead of mutating global state
  • Each IoRedisBackend method (get, set, del, scanDel, rateLimitHit, rateLimitHitSlidingWindow) already has per-call try-catch blocks that gracefully return null or blockedRateLimitBucket on transient errors, so the removal is safe

Closes #843

The IoRedis error handler was permanently replacing the global
'backend' variable with a MemoryBackend on any Redis error, with
no recovery mechanism. In multi-instance deployments, a transient
Redis blip permanently disabled distributed rate limiting on that
instance.

Fix: Remove the backend reassignment from the error handler. Each
IoRedisBackend method already has per-call try-catch blocks that
gracefully return null or blockedRateLimitBucket on transient errors.
The error handler now only logs the warning instead of mutating
global state.

Closes Coder-s-OG-s#843
@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

@ionfwsrijan is attempting to deploy a commit to the codersogs-3057's projects Team on Vercel.

A member of the Team first needs to authorize it.

@ionfwsrijan

Copy link
Copy Markdown
Contributor Author

@codersogs-code @Soumya-codr Please review this

@jakharmonika364

Copy link
Copy Markdown
Collaborator

CI is failing can you please fix it

@ionfwsrijan

Copy link
Copy Markdown
Contributor Author

@jakharmonika364 @Soumya-codr Please review now

@jakharmonika364 jakharmonika364 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix looks correct - good catch, and the per-call fail-closed fallback is already tested for both backends, so this is safe.

One ask before merge: this path (pickDefaultBackend's Redis client error handler) has zero test coverage, the existing cache.test.ts only constructs IoRedisBackend directly with mocks, never exercises this env-driven branch. That's likely how the original bug slipped in unnoticed.

Can you add a regression test: mock ioredis, set REDIS_URL, call pickDefaultBackend(), emit a synthetic error event, then assert cacheGet/rate-limit calls still route through the same IoRedisBackend instance instead of silently swapping to MemoryBackend?

Previously, a Redis error event permanently swapped the global backend to
MemoryBackend. The existing tests only constructed IoRedisBackend directly,
so this env-driven branch had zero coverage. Mock ioredis, load the module
with REDIS_URL set, emit a synthetic error event, and assert cacheGet and
rate-limit calls still route through the same IoRedis client.
@ionfwsrijan

Copy link
Copy Markdown
Contributor Author

@jakharmonika364 Please review now. I've made the changes

@jakharmonika364 jakharmonika364 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jakharmonika364 jakharmonika364 added level:advanced Advanced level difficulty quality:clean Clean, well-structured contribution type:bug Bug fix gssoc:approved Approved by GSSOC admin SSoC26 Hard ECSoC26 ECSoC26-L2 Medium good-pr and removed CI CD pending labels Aug 1, 2026
@jakharmonika364
jakharmonika364 merged commit 95ebda3 into Coder-s-OG-s:main Aug 1, 2026
2 of 3 checks passed
@ecsoc-sentinel ecsoc-sentinel Bot added ECSoC26-L2 Medium and removed ECSoC26-L2 Medium labels Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ECSoC26-L2 Medium ECSoC26 good-pr gssoc:approved Approved by GSSOC admin Hard level:advanced Advanced level difficulty quality:clean Clean, well-structured contribution SSoC26 type:bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Redis Error Handler Permanently Mutates Global Cache Backend with No Recovery

2 participants