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.
⚡ 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:
Precisão temporal com Redis ZSET
Burst handling com Lua scripts atômicos
Cache local quando Redis indisponível
Circuit Breaker Pattern
Proteção contra cascading failures com 3 estados:
- →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:
- • Operador clica "assumir conversa"
- • Redis latch bloqueia AI instantaneamente
- • Timer auto-resume configurável por tenant
- • Lazy finalize: summary gerado ao retomar
- • 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:
Nova conversa ou mudança de status
Mensagem cliente/AI normalizada
Mensagem do operador (WhatsApp/Web)
Trigger de refetch no frontend
Idempotency Gate
Proteção contra processamento duplicado:
X-Idempotency-Key🏗️ 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.