From 11cd6700b67a5039fa162ec1fecf2ea42596b3da Mon Sep 17 00:00:00 2001 From: kiel997 Date: Wed, 29 Jul 2026 09:24:37 +0100 Subject: [PATCH] feat(analytics): rate-limit POST /analytics/track to 20 req/min per IP Overrides the global throttle default for the event-tracking endpoint, which needs a more generous per-client limit than auth routes. Guard scoping is per-IP via the existing global ThrottlerGuard (#313). Verified locally: first 20 requests/min return 201, subsequent requests return 429 with a Retry-After header. Closes #552 --- backend/src/analytics/controllers/analytics.controller.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/src/analytics/controllers/analytics.controller.ts b/backend/src/analytics/controllers/analytics.controller.ts index 88d123f..1d564dc 100644 --- a/backend/src/analytics/controllers/analytics.controller.ts +++ b/backend/src/analytics/controllers/analytics.controller.ts @@ -1,5 +1,6 @@ import { Controller, Post, Body, Get, Query, UseGuards } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiQuery, ApiResponse } from '@nestjs/swagger'; +import { Throttle } from '@nestjs/throttler'; import { TrackEventProvider } from '../providers/track-event.provider'; import { GetOnboardingFunnelProvider } from '../providers/get-onboarding-funnel.provider'; import { GetRetentionCurveProvider } from '../providers/get-retention-curve.provider'; @@ -27,7 +28,9 @@ export class AnalyticsController { } @Post('track') + @Throttle({ default: { limit: 20, ttl: 60000 } }) @ApiOperation({ summary: 'Track an analytics event' }) + @ApiResponse({ status: 429, description: 'Too many requests — rate limit exceeded' }) async track(@Body() dto: TrackEventDto) { await this.trackEventProvider.track(dto); return { success: true };