Skip to content

fix: fail closed when no shared cache is configured in production - #866

Merged
jakharmonika364 merged 2 commits into
Coder-s-OG-s:mainfrom
ionfwsrijan:fix/issue-861-fail-closed-no-shared-cache
Aug 3, 2026
Merged

fix: fail closed when no shared cache is configured in production#866
jakharmonika364 merged 2 commits into
Coder-s-OG-s:mainfrom
ionfwsrijan:fix/issue-861-fail-closed-no-shared-cache

Conversation

@ionfwsrijan

Copy link
Copy Markdown
Contributor

Fix: Fail Closed When No Shared Cache Is Configured in Production (#861)

Problem

With no Redis/Upstash configured in production, pickDefaultBackend fell back to an in-process MemoryBackend. On serverless, each invocation gets its own memory, so rate limiting was effectively disabled (every invocation started with a fresh counter) — webhook and action throttling silently stopped working. Separately, IoRedisBackend used retryStrategy: () => null, permanently killing the client on the first transient blip.

Changes

  • src/lib/cache.ts
    • New BlockingBackend: every rate-limit hit reports over the limit (blocking), and all other cache ops are safe no-ops — no stale or cross-tenant reads.
    • pickDefaultBackend returns BlockingBackend whenever isProductionDeploy() is true and no distributed backend is configured, instead of silently degrading to memory.
    • New isProductionDeploy() gates on VERCEL_ENV === 'production' (Vercel Preview also sets NODE_ENV=production during next build) then falls back to NODE_ENV.
    • IoRedis retryStrategy now uses bounded backoff (min(times*250, 5000), giving up after 10 attempts) instead of failing permanently.
  • src/lib/rate-limit.ts: kept its own local isProductionDeploy copy so tests that partially mock @/lib/cache don't break.

Impact

A misconfigured production deploy blocks unthrottled traffic instead of silently disabling rate limits, and a transient Redis blip no longer kills the cache client for the life of a warm instance.

Closes #861

@vercel

vercel Bot commented Aug 2, 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.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Hey @ionfwsrijan

You have 4 open PRs right now. The limit is 3 at a time.

Please get your existing PRs merged or closed before opening new ones:

This PR will remain open but won't be reviewed until you're under the limit. See our Contributing Guidelines for details.

@ionfwsrijan

Copy link
Copy Markdown
Contributor Author

@Soumya-codr @codersogs-code Please review this

@ionfwsrijan

Copy link
Copy Markdown
Contributor Author

@jakharmonika364

@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.

Nice fix - this closes the exact Preview-deployment gap left over from #854 (that PR fixed the rate-limit.ts gate but cache.ts's pickDefaultBackend() was still on raw NODE_ENV, so Preview could still hit the wrong branch). BlockingBackend implements CacheBackend correctly and reuses the existing blockedRateLimitBucket() convention. The retryStrategy fix for the permanent-death-on-first-blip bug is a good catch too.

One tiny nit: rate-limit.ts's isProductionDeploy() duplicate is justified by a comment about tests that partially mock @/lib/cache, but I don't see any test doing that today - not a blocker, just flagging that these two copies will need manual sync if either changes in the future.

@jakharmonika364 jakharmonika364 added the Needs author reply Author need to reply label Aug 2, 2026
@ionfwsrijan

Copy link
Copy Markdown
Contributor Author

@jakharmonika364 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.

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-L3 Hard good-pr and removed Needs author reply Author need to reply labels Aug 3, 2026
@jakharmonika364
jakharmonika364 merged commit fd955fb into Coder-s-OG-s:main Aug 3, 2026
2 of 3 checks passed
@ecsoc-sentinel ecsoc-sentinel Bot added ECSoC26-L2 Medium and removed ECSoC26-L3 Hard labels Aug 3, 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] Rate Limiting Silently Becomes a No-Op in Production When Redis/Upstash Is Missing or Hiccups at Startup

2 participants