Gateway Inteligente

Backend Orchestrator

Gateway enterprise multi-tenant com rate limiting distribuído, circuit breaker, handover dual-mode (operator + AI-initiated), WebSocket real-time e fail-closed resilience.

<50ms
Gateway Latency
100k+
Req/min/tenant
3
Retry Strategies
99.9%
Uptime

O Problema

Em sistemas de atendimento multi-tenant, o gateway é o ponto crítico de falha. Problemas comuns:

  • Noisy Neighbor: Um tenant com tráfego alto derruba todos os outros
  • Cascading Failures: AI Engine lento bloqueia todo o sistema
  • Handover Chaos: AI responde quando humano está atendendo
  • Idempotency Bugs: Mesma mensagem processada múltiplas vezes
  • Frontend Desync: UI não reflete estado real das conversas

A Solução

Enterprise Rate Limiting

Sistema de rate limiting multi-camada com algoritmos adaptativos:

Sliding Window

Precisão temporal com Redis ZSET

Token Bucket

Burst handling com Lua scripts atômicos

Local Fallback

Cache local quando Redis indisponível

Tenant Tiers: FREE (10 req/min) → BASIC (50) → PROFESSIONAL (200) → ENTERPRISE (unlimited)

Circuit Breaker Pattern

Proteção contra cascading failures com 3 estados:

CLOSED
OPEN
HALF_OPEN
  • failure_threshold: 5 falhas consecutivas abrem o circuito
  • recovery_timeout: 60s antes de testar novamente
  • half_open_max_calls: 10 requests de teste antes de fechar

Handover Dual-Mode

Dois modos de transição AI ↔ Humano:

👤 Operator Takeover
  • • Operador clica "assumir conversa"
  • • Redis latch bloqueia AI instantaneamente
  • • Timer auto-resume configurável por tenant
  • • Lazy finalize: summary gerado ao retomar
🤖 AI-Initiated
  • • AI detecta problema (ERP failure, complexidade)
  • • Context injection com prioridade máxima
  • • Mensagem natural para cliente
  • • Histórico multi-handover preservado

Fail-Closed Resilience

Quando Redis está indisponível, o sistema bloqueia AI (não fica silencioso):

HandoverGateDecision:
  blocked: true
  reason: "redis_unavailable"  # Fail-closed
  retry_count: 3               # Exponential backoff + jitter

# Cliente recebe: "Um momento, estamos te transferindo..."
# NÃO: silêncio total (fail-open)
              

Retry Strategy: 3 tentativas com exponential backoff (50ms base) + jitter aleatório

WebSocket Real-Time

Broadcasting de eventos para sincronização frontend:

conversation_update

Nova conversa ou mudança de status

new_message

Mensagem cliente/AI normalizada

operator_message

Mensagem do operador (WhatsApp/Web)

cache_invalidation

Trigger de refetch no frontend

Idempotency Gate

Proteção contra processamento duplicado:

1Request chega com X-Idempotency-Key
2Check Redis: já processado? → retorna cached response
3Slot reservado → processa request
4Response cacheada com TTL de 24h

🏗️ Arquitetura

┌─────────────────────────────────────────────────────────────┐
│                    BACKEND ORCHESTRATOR                     │
│                    (Gateway Enterprise)                     │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────┐    ┌─────────────┐    ┌─────────────┐    │
│   │  Rate       │    │  Circuit    │    │  Handover   │    │
│   │  Limiter    │───▶│  Breaker    │───▶│  Gate       │    │
│   │  (Multi-tier)     │    │  (3 states) │    │  (Fail-closed)   │    │
│   └─────────────┘    └─────────────┘    └─────────────┘    │
│         │                  │                  │             │
│         └──────────────────┴──────────────────┘             │
│                           │                                 │
│                    ┌──────▼──────┐                          │
│                    │  Chat       │                          │
│                    │  Orchestrator│                         │
│                    │  + Idempotency│                        │
│                    └──────┬──────┘                          │
│                           │                                 │
│         ┌─────────────────┼─────────────────┐              │
│         ▼                 ▼                 ▼              │
│   ┌──────────┐    ┌──────────────┐   ┌──────────┐         │
│   │ AI Engine│    │ Memory Engine│   │ WebSocket│         │
│   │ (LangGraph)   │ (PostgreSQL) │   │ Broadcast│         │
│   └──────────┘    └──────────────┘   └──────────┘         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Request Flow:
1. Rate Limit Check (per-tenant tier)
2. Circuit Breaker (protect downstream)
3. Handover Gate (AI blocking)
4. Idempotency Check (dedupe)
5. AI Engine Call (with timeout)
6. WebSocket Broadcast (real-time)
7. Cache Response (24h TTL)

🎯 Decisões Técnicas

Por que fail-closed e não fail-open?

Em atendimento ao cliente, silêncio é pior que resposta de fallback. Fail-closed garante que o cliente sempre receba feedback ("estamos te transferindo") mesmo quando Redis está indisponível. Fail-open deixaria o cliente esperando indefinidamente.

Por que Redis latch e não database flag?

Redis latch com TTL automático elimina a necessidade de cleanup workers. Se o operador esquecer de "devolver" a conversa, o TTL expira e AI retoma automaticamente. Database flags precisariam de cron jobs para timeout.

Por que sliding window e não fixed window?

Fixed window tem o problema de "boundary burst": 100 requests no segundo 59 + 100 no segundo 0 = 200 requests em 2 segundos. Sliding window distribui uniformemente e evita esse pico.

Por que Lua scripts para token bucket?

Token bucket precisa de operações atômicas (read-modify-write). Sem Lua, teríamos race conditions entre GET e SET. Lua scripts executam atomicamente no servidor Redis, garantindo consistência mesmo com milhares de requests concorrentes.

Stack Técnica

Python 3.12FastAPIRedis 7HTTPX (async)WebSocketLua ScriptsJWT AuthPrometheusstructlog