From 4a159d2b6cf2e1d9876e18d1d63fbef160dbb7db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sat, 9 May 2026 02:01:17 +0200 Subject: [PATCH] fix(insights): cache hits no longer burn rate-limit tokens P13. Move `checkRateLimit` below the 24h cache-return path so a request that gets served from the cached `insightsCachedText` never consumes one of the 2/hour LLM-generation tokens. A user reloading the dashboard a few times no longer locks themselves out of a fresh refresh for an hour. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/app/api/insights/generate/route.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/app/api/insights/generate/route.ts b/src/app/api/insights/generate/route.ts index 64220042a..e09dd799f 100644 --- a/src/app/api/insights/generate/route.ts +++ b/src/app/api/insights/generate/route.ts @@ -15,11 +15,6 @@ export const POST = apiHandler(async (request: NextRequest) => { const { user } = await requireAuth(); const userId = user.id; - const rl = await checkRateLimit(`insights:${userId}`, 2, 60 * 60 * 1000); - if (!rl.allowed) { - return apiError("Maximum 2 insight generations per hour.", 429); - } - const dbUser = await prisma.user.findUnique({ where: { id: userId }, select: { @@ -53,6 +48,15 @@ export const POST = apiHandler(async (request: NextRequest) => { } } + // P13: rate-limit check moved BELOW the cache return so a hit on the + // 24h cache never burns one of the 2/hour LLM-generation tokens. + // Otherwise a noisy reload loop on the dashboard would lock out real + // refreshes for an hour for no benefit. + const rl = await checkRateLimit(`insights:${userId}`, 2, 60 * 60 * 1000); + if (!rl.allowed) { + return apiError("Maximum 2 insight generations per hour.", 429); + } + const provider = await resolveProvider(userId); if (provider.type === "none") {