Runbook: Rate limit exhausted (per supplier credential)

Severity (default): P2. Owner: ingestion team / on-call. Связанные алерты:

  • etm_credential_usage_ratio{credential_id} > 0.85 за час.
  • 5+ подряд 429/403 на одной credential.
  • circuit_breaker_open_total{credential_id} > 0.

Симптом

  • Падает rate observations для конкретной credential / поставщика.
  • Pricing отвечает с freshness_status=stale для затронутых клиентов.
  • Customer credential может уйти в failing.

Диагностика

# 1. Состояние бакетов в Redis
kubectl -n tracium exec deploy/redis -- redis-cli --scan --pattern 'ratelimit:etm:*' | head -20
kubectl -n tracium exec deploy/redis -- redis-cli GET "ratelimit:etm:<CRED_ID>:goods_read"
# 2. Метрики
# Через Grafana: дашборд "Ingestion → <supplier>"
# Смотреть: usage_ratio, requests_total{status=429}
# 3. Какие endpoints горят
kubectl -n tracium logs deploy/ingestor --since=15m \
  | grep -E "credential_id=<CRED_ID>" \
  | grep -E "status=429|status=403|backoff" \
  | awk '{print $NF}' | sort | uniq -c | sort -rn

Возможные причины:

  • A: Естественный пик (полный rebuild каталога после обновления identity profiles).
  • B: Баг в коннекторе — request loop без backoff.
  • C: Несколько реплик ingestor’а пишут одновременно (rate limiter не работает корректно).
  • D: ETM (или другой supplier) уменьшил лимит в одностороннем порядке.

Смягчение

A: Естественный пик

# Временно уменьшить параллелизм worker pool
kubectl -n tracium exec deploy/admin-api -- \
  curl -X PATCH localhost:8080/v1/admin/connectors/<supplier>/workers \
  -d '{"max_concurrent_per_credential":1,"ttl":"2h"}'

B: Баг коннектора

Срочно — pause connector:

kubectl -n tracium exec deploy/admin-api -- \
  curl -X POST localhost:8080/v1/admin/connectors/<supplier>/pause \
  -d '{"reason":"investigation","ttl":"30m"}'

Потом — поиск root cause в логах коннектора.

C: Распределённый rate limiter не работает

# Проверить, что Redis достижим из всех реплик
for pod in $(kubectl -n tracium get pods -l app=ingestor -o name); do
  kubectl -n tracium exec $pod -- redis-cli -h redis ping
done

Если Redis нестабилен → fail-safe локальный limiter (более консервативный) должен включаться автоматически. Проверить метрику rate_limiter_fallback_local_total > 0.

D: Supplier изменил лимит

Снизить нашу конфигурацию через override:

kubectl -n tracium exec deploy/admin-api -- \
  curl -X PATCH localhost:8080/v1/admin/connectors/<supplier>/rate-limits \
  -d '{"<endpoint>":{"rate":1,"period":"2s"},"ttl":"24h"}'

Параллельно — открыть тикет на пересмотр <supplier>/rate-budget.md и официальное согласование с поставщиком.

Устранение root cause

  • A: лучшее планирование пиковых rebuild’ов (off-peak окна).
  • B: integration tests против mock с rate-limit assertion.
  • C: e2e тест распределённого rate limiter с N репликами.
  • D: договор с поставщиком на минимальный гарантированный rate.

Эскалация

  • 1 ч без mitigation → #oncall-ingestion.
  • Затронуты > 50% клиентских credentials → #oncall-product (массовая stale).

Связано

  • ADR-0008 (rate limiter).
  • 40-operations/rate-limits.md
  • 30-services/ingestion/connectors/etm/rate-budget.md
  • etm-session-failure.md