Files
ai-coding-starter-kit-v2/docs/production/rate-limiting.md
T
patrickandClaude Sonnet 5 4a19335a1e feat: rework starter kit for self-hosted deploy (Vite/React + Fastify/Drizzle/Postgres)
Replace Next.js/Supabase/Vercel stack with a self-hostable setup: Vite+React
frontend, Fastify+Drizzle+PostgreSQL backend with own JWT auth, deploy via
git pull + rsync + systemd (checkout/service separated, updates pulled from
Gitea). Adds a reference auth route (register/login/me) as the canonical
pattern for new routes. Updates all skills/rules/agents/docs to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BMdBJfD9TT6XUU2NqGG1PN
2026-09-08 11:42:47 +02:00

1.6 KiB

Rate Limiting

Prevent abuse, brute-force, and excessive API usage.

When to Add Rate Limiting

  • MVP: Optional (focus on features first)
  • Production with users: Recommended on auth endpoints and public APIs
  • Public-facing APIs: Required

Setup with @fastify/rate-limit

No external service needed — in-memory by default, works fine for a single backend instance.

1. Install Dependency

cd backend && npm install @fastify/rate-limit

2. Register Globally

// backend/src/server.ts
import rateLimit from "@fastify/rate-limit";

await app.register(rateLimit, {
  max: 100,
  timeWindow: "1 minute",
});

3. Tighter Limits on Specific Routes

// backend/src/routes/auth.ts
app.post("/api/auth/login", {
  config: {
    rateLimit: { max: 5, timeWindow: "1 minute" },
  },
}, async (request, reply) => {
  // login handler
});

4. Response on Limit Exceeded

@fastify/rate-limit returns HTTP 429 automatically with Retry-After and X-RateLimit-* headers — no manual handling needed.

Endpoint Type Limit Window
Login/Register 5 requests 1 minute
Password Reset 3 requests 5 minutes
General API 30 requests 10 seconds
File Upload 5 requests 1 minute

Multi-Instance Deployments

If the backend ever runs as more than one process/instance behind a load balancer, switch the plugin's store to Redis (@fastify/rate-limit supports a custom redis client option) so limits are shared across instances instead of per-process.