Repository navigation
[AISAGE-729] refactor(gateway): replace free model database rate limit with Vercel Firewall rule - #7534
Conversation
… Firewall rule Rate-limited free models (free Gemma behind kilo-auto/small) now count against the 'free-model-inference' Vercel Firewall rule instead of counting and inserting free_model_usage rows on every request. Removes the unreachable anonymous promotion limit and the admin free-model-usage page, stats routes, and rate-limit test tool. The free_model_usage table and its cleanup cron stay until the table is dropped.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryReviewed the free-model rate-limit migration from DB-backed counting to the shared Vercel Firewall helper; the refactor is internally consistent, all removed symbols have no remaining references, and the module-level Sentry throttle Map is bounded by fixed rule IDs (no leak). Files Reviewed (20 files)
Verified: no dangling references to removed exports ( Reviewed by deepseek-v4.1-flash · Input: 87.3K · Output: 16.9K · Cached: 1.4M Review guidance: REVIEW.md from base branch |
Summary
Rate-limited free models (today only free Gemma, which free users reach through
kilo-auto/smallfor session titles and similar) no longer countfree_model_usagerows and insert one per request. They now count against a Vercel Firewall rule,free-model-inference, through@vercel/firewall'scheckRateLimit. The rule keeps the existing limit of 200 requests per hour per key.user:<id>and still need auth. Everything else is keyedip:<address>.gateway-account-rate-limit.tsintofirewall-rate-limit.ts, and both rules use it. The throttle is now per rule, so one missing rule can't hide another.PROMOTION_MODEL_LIMIT_REACHEDresponse and thepromotion_limit_reachederror type are removed too./admin/free-model-usagepage, the free and promoted model usage stats routes, theadmin.freeModelUsagetRPC router (including "rate limit my IP"), and the related constants. With no new writes, they would only show stale data.free_model_usagetable, its schema, the FK nulling on user deletion, and the cleanup cron, which drains the existing rows before the table is dropped in a follow-up.Required before deploy: create the firewall rule
checkRateLimittreats an unknown rule ID as "not limited". Until the rule exists, the free-model limit is off and Sentry getsFirewall rate limit 'free-model-inference' is not configured(throttled to once a minute per instance, tagsource:free_model_inference). Publishing the rule before this deploys is harmless, because nothing calls it yet.Create the rule in each Vercel project that serves the LLM proxy. Rules and counters are separate per project.
kilocode-ai-gateway/api/v1kilocode-app/api/openrouter,/api/gatewaykilocode-global-appkilocode-app, only if it still deploysIn each project:
Free model inference.@vercel/firewall, Rate limit IDfree-model-inference(exact match).ip:<address>oruser:<id>, which replaces the IP key.To trial it first, set the action to Log, watch the rule's traffic on the Firewall overview, then switch to 429. The limit can be tuned in the dashboard without a deploy.
How this differs from the old database limit
The number and window are the same, but the behaviour is not identical:
kilocode-ai-gatewayruns in fra1 and sfo1. A key also gets a separate allowance in each project. The old database count was global, so the real ceiling is somewhat higher.The existing account cap needs its
gateway-inferencerule in the same projects. A missing rule shows up in Sentry as the same "not configured" message forgateway-inference.Verification
Re-run after merging the latest
main(4e8bca43c):firewall-rate-limit,free-model-rate-limit,gateway-account-rate-limit,llm-proxy,llm-proxy-helpers,typesafe/handler,models,feature-detection. 8 suites, 386 tests passed. Newllm-proxycases cover the per-IP key, the per-user key, and the auth requirement for server-side products on Cloudflare IPs.tsgotypecheck passes forapps/web,apps/ai-gatewayandpackages/web-shared, and thepackages/trpcbuild passes.oxlinton changed paths,oxfmt --list-different, andgit diff --checkwere clean.