# Backend: Rate Limiting — In-Memory Проблема **Контекст**: В `backend/internal/middleware/ratelimit.go` используется in-memory token bucket (golang.org/x/time/rate). В `main.go:54` создаётся глобальный лимитер на 60 req/min на IP. ## Суть **In-memory rate limiter не работает в production** при: - Масштабировании (multiple replicas) — каждый контейнер имеет свой счётчик - Рестарте контейнеров — счётчики сбрасываются - Загрузке через Load Balancer — IP клиента может попадать на разные инстансы ## Код (проблемное место) ```go // backend/cmd/api/main.go:54 rl := middleware.NewRateLimiter(rate.Limit(60), 60) // In-memory! r.Use(rl.Middleware()) ``` ```go // backend/internal/middleware/ratelimit.go (упрощённо) type RateLimiter struct { limiter *rate.Limiter // In-memory token bucket } ``` ## Решение: Redis-based Rate Limiting Использовать Redis с sliding window / token bucket алгоритмом. Ключ: `ratelimit:{ip}:{endpoint}` или `ratelimit:{user_id}:{endpoint}`. ### Библиотеки: - `github.com/ulule/limiter/v3` — поддерживает Redis, in-memory, sliding window - Или самописный на Lua-скрипте для атомарности ### Пример с ulule/limiter: ```go import ( "github.com/redis/go-redis/v9" "github.com/ulule/limiter/v3" "github.com/ulule/limiter/v3/drivers/store/redis" ) store := redis.NewStoreWithOptions(redisClient, limiter.StoreOptions{ Prefix: "ratelimit", }) rate := limiter.Rate{Period: 1*time.Minute, Limit: 60} instance := limiter.New(store, rate) ``` ## Настройка для разных эндпоинтов (по API_CONTRACT.md) | Эндпоинт | Лимит | Ключ | |----------|-------|------| | `/auth/*` | 10/min | IP | | `GET /places` | 60/min | UserID или IP | | `POST /places` | 10/min | UserID | | `/admin/*` | 100/min | UserID | ## Альтернативы | Подход | Плюсы | Минусы | |--------|-------|--------| | **Redis + ulule/limiter (рекомендую)** | Работает в кластере, гибкие правила | Зависимость от Redis | | **nginx rate limiting** | На уровне инфраструктуры | Меньше гибкости, сложнее per-user | | **Cloudflare / API Gateway** | Не трогает код | Vendor lock-in, платное | ## Связанные заметки - [[decision-rate-limiter-redis]] - [[architecture-overview]] - [[deploy-production-readiness]] ## Источник Задача: Code review PhotoPlaces — rate limiter не работает в проде ## Теги #backend #rate-limiting #redis #scaling #critical #best-practice