Skip to content

feat(prediction): opt-in default rate limit keyed by user or IP - #1097

Open
diecoscai wants to merge 1 commit into
fix/prediction-optional-authfrom
fix/prediction-rate-limit
Open

diecoscai wants to merge 1 commit into
fix/prediction-optional-authfrom
fix/prediction-rate-limit

Conversation

@diecoscai

Copy link
Copy Markdown

Why

/api/v1/prediction has no limit unless someone configures one per chatflow (utils/rateLimit.ts: no limiter → next()). Anyone with the id of a public chatflow can call it without limit, and every call runs the flow (an LLM call we pay for).

Stacked on #1095 (optional auth on /prediction). Pairs with #1096 (TRUST_PROXY=1), which stops callers from faking their IP; without #1096 the IP-keyed part of this limit can be bypassed the same way configured limits are today.

What changes

  • Opt-in default limit. When DEFAULT_RATE_LIMIT_MAX is a positive integer, a chatflow with no configured limit gets DEFAULT_RATE_LIMIT_MAX requests per DEFAULT_RATE_LIMIT_WINDOW_SECONDS (default 60). Unset or invalid (0, -1, 1.5, abc) → no change from today.
  • Keyed by user when known, else by IP, per chatflow: <chatflowId>:user:<userId> or <chatflowId>:ip:<ip>. People behind one office IP using the extension don't share a bucket. The key never contains the email.
  • Configured chatflow limits are unchanged: they win over the default and still key by IP.
  • Only /prediction. /vectors/upsert keeps today's behavior (bulk ingestion scripts call it many times a minute).
  • Queue mode uses the Redis store (prefix rl:default:), same as configured limits.
  • Order: optional auth now runs before the limiter, so the key can use req.user. Cost: a forged JWT pays one signature check (no DB) before the 429.
  • addRateLimiter body moved to a private createLimiter; behavior unchanged.

Tests (all local)

  • Unit (test/utils/rateLimit, 15, real express-rate-limit): default off, invalid values ignored, limit hit on the 3rd call, per chatflow, two users on one IP separate, anonymous on one IP shared, configured limit wins and keys by IP, /vectors path ignores the default, no id doesn't throw, Redis store prefix, no email in key. Router: auth runs before the limiter.
  • Integration (test/integration/rateLimit, Postgres 16 + real RS256 tokens, DEFAULT_RATE_LIMIT_MAX=2): alice 200,200,429 then bob on the same IP 200; anonymous 200,200,429; forged token lands in the anonymous IP bucket and creates no user. With the router order reverted, bob gets 429 (the test catches it).
  • Mutation (Stryker 8.7.1 on the changed lines): 33 killed, 8 survived, all equivalent (header flags, the moved Redis sendCommand, the no-id bucket name, max >= 0 which express-rate-limit 6.11.2 also treats as unlimited, and two pre-existing route strings). A first run found a real gap (invalid DEFAULT_RATE_LIMIT_MAX values); test added.
  • Regression: same failures as staging before this branch (documentstore 3 tests, auth/middleware suite fails to load), all new tests pass. tsc and eslint exit 0.
  • The shared Auth0 + Postgres setup moved to test/integration/auth0Fixture.ts; test/integration/prediction uses it and still passes 9/9.

Rollout

Off everywhere until DEFAULT_RATE_LIMIT_MAX is set. Plan: after #1096 is deployed and /api/v1/ip is verified on staging.ias, set it there first. The number comes from Langfuse peaks (3× the real per-minute peak per person, min 20) and needs Max's OK before IAS production.

🤖 Generated with Claude Code

When DEFAULT_RATE_LIMIT_MAX is set, chatflows with no configured limit get a
default per-minute limit on /prediction. Identified callers (optional auth from
the previous commits) get their own bucket; anonymous callers are counted by IP.
Configured chatflow limits and /vectors are unchanged. Auth now runs before the
limiter so the key can use req.user.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@diecoscai diecoscai self-assigned this Nov 11, 2026
@vercel

vercel Bot commented Nov 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
answerai-docs Building Building Preview Nov 11, 2026 6:50pm UTC
the-answerai Error Error Nov 11, 2026 6:50pm UTC

Request Review

This branch had an error being deployed

1 failed and 1 active deployments
Preview – answerai-docs — 375d6563 Deployed Nov 11, 2026 by vercel[bot]
Preview – the-answerai — 375d6563 Deployed Nov 11, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant