backend-rate-limiting.md 2.9 KB

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 клиента может попадать на разные инстансы

Код (проблемное место)

// backend/cmd/api/main.go:54
rl := middleware.NewRateLimiter(rate.Limit(60), 60)  // In-memory!
r.Use(rl.Middleware())
// 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:

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