From 05ccdc66da4e095d76218de2b9378750397b1bb1 Mon Sep 17 00:00:00 2001 From: Ajax Davis Date: Fri, 9 Jan 2026 04:51:33 +1000 Subject: [PATCH] fix: add timeout to Vercel KV rate limiter to prevent hanging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rate limiter was calling @vercel/kv without a timeout, which could hang indefinitely if KV is not configured or responding. This adds a 2-second timeout to prevent requests from timing out. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- apps/web/src/lib/rate-limit.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/web/src/lib/rate-limit.ts b/apps/web/src/lib/rate-limit.ts index f0d69bb..a23b62c 100644 --- a/apps/web/src/lib/rate-limit.ts +++ b/apps/web/src/lib/rate-limit.ts @@ -106,11 +106,20 @@ export const STRICT_RATE_LIMIT: RateLimitConfig = { }; /** - * Get rate limit entry from Vercel KV + * Helper to add timeout to promises + */ +function withTimeout(promise: Promise, timeoutMs: number): Promise { + const timeout = new Promise((resolve) => setTimeout(() => resolve(null), timeoutMs)); + return Promise.race([promise, timeout]); +} + +/** + * Get rate limit entry from Vercel KV (with timeout) */ async function getKVEntry(key: string): Promise { try { - return await kv.get(key); + const result = await withTimeout(kv.get(key), 2000); + return result; } catch (error) { console.error('[Rate Limit] KV get error:', error); return null; @@ -118,11 +127,12 @@ async function getKVEntry(key: string): Promise { } /** - * Set rate limit entry in Vercel KV + * Set rate limit entry in Vercel KV (with timeout, fire-and-forget) */ async function setKVEntry(key: string, entry: RateLimitEntry, ttlSeconds: number): Promise { try { - await kv.set(key, entry, { ex: ttlSeconds }); + // Fire and forget - don't wait for result, just timeout if slow + withTimeout(kv.set(key, entry, { ex: ttlSeconds }), 2000); } catch (error) { console.error('[Rate Limit] KV set error:', error); }