Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions lib/rate-limit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,17 @@ interface RateLimitResult {
}

/**
* In-memory rate limiter to prevent basic DoS/spam (Denial of Wallet).
* Rate limiter to prevent basic DoS/spam (Denial of Wallet).
*
* Note: In a serverless environment, this resets per cold-start/instance,
* but it is highly effective at stopping aggressive single-instance spikes.
* For multi-instance strict syncing, a Redis store (Vercel KV/Upstash) should be used.
* When Upstash Redis / Vercel KV is configured (KV_REST_API_URL + KV_REST_API_TOKEN
* environment variables), rate limit state is persisted across restarts and shared
* across all serverless instances via atomic INCR + EXPIRE operations.
*
* Falls back to an in-memory TTL cache when KV is not configured. In this mode,
* state resets on cold start / server restart, but it is highly effective at
* stopping aggressive single-instance spikes during normal operation.
*
* @see https://upstash.com/docs/rate-limiting/quickstart for KV setup instructions.
*/
export class RateLimiter {
private cache: DistributedCache<{ count: number; resetAt: number }>;
Expand Down
14 changes: 14 additions & 0 deletions services/github/refresh-rate-limiter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ interface RefreshLimitRecord {
windowStart: number;
}

/**
* In-memory rate limiter for manual cache refresh operations.
*
* Limits how frequently a single IP can trigger a manual data refresh.
* Uses a TTL-based in-memory cache that expires entries automatically.
*
* ⚠️ Limitation: State is per-process only. In serverless deployments
* (Vercel, AWS Lambda), each cold start resets the limiter. This is
* acceptable for abuse prevention on a single instance, but not suitable
* for strict cross-instance rate limiting.
*
* For production deployments requiring persistent state, consider using
* Upstash Redis or Vercel KV by importing from '@/lib/rate-limit' instead.
*/
export class RefreshRateLimiter {
private static instance: RefreshRateLimiter;

Expand Down
Loading