Como 14 Minutos de Downtime Podem Custar €47.000 em Reembolsos
Imagine este cenário: a base de dados primária de uma plataforma SaaS atinge 100% de utilização de CPU. Em 14 minutos, toda a plataforma fica sem resposta. Durante essa janela, 2.847 utilizadores perdem acesso a meio do workflow. Pedidos de modelos IA ficam em fila e expiram. Transações de créditos falham silenciosamente.
A causa raiz? Um único cliente a executar uma exportação em massa de 340.000 registos através de um endpoint de API que não estava propriamente limitado. Um tenant a derrubar toda a plataforma.
Este tipo de incidente força um repensar arquitetural completo. Os padrões abaixo mostram como plataformas evoluem para servir 3x o tráfego com 99,97% de uptime após aprender estas lições difíceis.
A Árvore de Decisão de Multi-Tenancy
Antes de escrever uma única linha de código, tens de decidir como os tenants partilham (ou não) recursos. Esta decisão afeta tudo a jusante.
Tudo Partilhado (Multi-Tenancy a Nível de Base de Dados)
Todos os tenants partilham a mesma base de dados, distinguidos por uma coluna tenant_id em cada tabela.
Vantagens:
- Custo de infraestrutura mais baixo por tenant
- Modelo de deployment mais simples
- Analytics cross-tenant fácil
Desvantagens:
- Problema de vizinho barulhento (um tenant afeta todos os outros)
- Isolamento de dados complexo (cada query deve filtrar por tenant)
- Desafios regulatórios (algumas indústrias requerem separação física)
Quando usar: SaaS em fase inicial com restrições de orçamento, base de clientes homogénea, sem requisitos de compliance estritos.
Erro comum: Muitas plataformas começam aqui. Quando clientes Enterprise pedem recursos dedicados, não conseguem oferecer sem uma migração major.
Infraestrutura Partilhada, Bases de Dados Isoladas
Cada tenant obtém a sua própria base de dados mas partilha servidores de aplicação e infraestrutura.
Vantagens:
- Forte isolamento de dados
- Backup e restore por tenant
- História de compliance mais fácil
Desvantagens:
- Gestão de pool de conexões torna-se complexa
- Migrações de schema devem correr em todas as bases de dados
- Maior overhead operacional
Quando usar: Indústrias reguladas, clientes com requisitos de residência de dados, B2B SaaS com requisitos contratuais de isolamento.
Totalmente Isolado (Deployments Single-Tenant)
Cada tenant obtém infraestrutura dedicada—as suas próprias instâncias de aplicação, bases de dados, e frequentemente o seu próprio namespace Kubernetes ou conta cloud.
Vantagens:
- Isolamento completo (performance, segurança, compliance)
- Customização por tenant possível
- Fronteiras de segurança limpas
Desvantagens:
- Custo mais alto por tenant
- Complexidade de deployment escala linearmente com clientes
- Upgrades tornam-se um pesadelo de coordenação
Quando usar: Clientes enterprise a pagar €10k+/mês, contratos governamentais, indústrias altamente reguladas.
A Nossa Abordagem Híbrida
Após o incidente de Março, implementámos isolamento por tiers:
Tier Standard: Base de dados partilhada com segurança a nível de linha. Dados de tenant filtrados na camada de aplicação e enforced na camada de base de dados usando políticas PostgreSQL RLS.
Tier Professional: Base de dados isolada por tenant, infraestrutura de aplicação partilhada. Connection pooling via PgBouncer com pools por tenant.
Tier Enterprise: Namespace Kubernetes dedicado com compute, storage e networking isolados. Efetivamente single-tenant dentro de infraestrutura partilhada.
Este modelo híbrido aumentou os nossos custos de infraestrutura em 40% mas eliminou totalmente o impacto de performance cross-tenant.
Desenhar para 100+ Modelos IA
O desafio único de plataformas IA multi-modelo: encaminhar pedidos para 100+ fornecedores de modelos IA, cada um com diferentes rate limits, preços, características de latência e modos de falha.
O Padrão Gateway
Cada pedido IA flui através de um gateway unificado que trata:
┌─────────────────┐
│ API Gateway │
│ (Rate Limits) │
└────────┬────────┘
│
┌────────▼────────┐
│ Router Service │
│ (Model Selection)│
└────────┬────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
┌────────▼─────┐ ┌────────▼─────┐ ┌────────▼─────┐
│ OpenAI │ │ Anthropic │ │ Google │
│ Adapter │ │ Adapter │ │ Adapter │
└──────────────┘ └──────────────┘ └──────────────┘
Lógica do Router Service:
- Verificar tier e saldo de créditos do utilizador
- Determinar modelo ótimo baseado no tipo de pedido e preferência do utilizador
- Verificar health scores dos fornecedores (mantidos por monitores em background)
- Aplicar regras de fallback se fornecedor primário estiver degradado
- Encaminhar para adapter apropriado
Responsabilidades do Adapter:
- Traduzir o nosso formato de API unificado para formato específico do fornecedor
- Tratar autenticação e rotação de credenciais
- Implementar padrões circuit breaker
- Recolher métricas de latência e erros
Arquitetura do Sistema de Créditos
Os créditos são a moeda universal em todas as operações IA. O sistema de créditos deve ser:
- Preciso: Os utilizadores confiam no seu saldo
- Rápido: Não pode adicionar latência a cada pedido
- Consistente: Sem gastos duplos, sem créditos perdidos
A nossa implementação usa um padrão event-sourced:
-- Eventos de crédito são append-only
CREATE TABLE credit_events (
id UUID PRIMARY KEY,
tenant_id UUID NOT NULL,
event_type VARCHAR(50), -- 'purchase', 'usage', 'refund', 'adjustment'
amount DECIMAL(10, 4),
model_id VARCHAR(100),
request_id UUID,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);-- Saldo materializado para leituras rápidas
CREATE MATERIALIZED VIEW credit_balances AS
SELECT
tenant_id,
SUM(CASE WHEN event_type IN ('purchase', 'refund') THEN amount ELSE -amount END) as balance
FROM credit_events
GROUP BY tenant_id;
Para verificações de saldo em tempo real, mantemos uma cache em memória (Redis) que é atualizada assincronamente após cada transação. A view materializada serve como fonte autoritativa, refrescada a cada 5 minutos e on-demand para saldos disputados.
Lidar com Outages de Fornecedores
Fornecedores de IA caem. A OpenAI teve 7 outages significativos em 2024. A tua arquitetura deve lidar com isto graciosamente.
A nossa abordagem: Fallback automático com consentimento do utilizador
Os utilizadores configuram preferências de fallback:
- Permitir fallback automático para modelos equivalentes (ex: GPT-4 → Claude 3.5 Sonnet)
- Permitir fallback automático para modelos de tier inferior (ex: GPT-4 → GPT-4o-mini)
- Sem fallback (falhar o pedido)
Quando o modelo primário não está disponível:
- Circuit breaker abre após 3 falhas consecutivas
- Sistema verifica preferências de fallback do utilizador
- Encaminha para modelo de fallback se permitido
- Regista modelo original e de fallback para transparência de faturação
Ajuste de créditos: Se o modelo de fallback custa menos, creditamos a diferença. Se custa mais, absorvemos a diferença. Isto constrói confiança.
Padrões de Escalabilidade Que Realmente Funcionaram
Padrão 1: Colocar em Fila Tudo Que Pode Esperar
Nem todos os pedidos precisam de processamento síncrono. Identificámos três categorias:
Síncrono (< 30s esperado):
- Chat completions
- Gerações simples
- Análise em tempo real
Async-by-default (30s - 5min):
- Geração de imagem
- Processamento de documentos longos
- Traduções em lote
Background (> 5min):
- Jobs de fine-tuning
- Exportações em massa
- Geração de relatórios
Mover workloads async para filas (usamos Amazon SQS com worker pods) reduziu a carga do nosso servidor API em 60% e melhorou a latência P95 para pedidos síncronos de 4,2s para 890ms.
Padrão 2: Read Replicas para Analytics
Dashboards de utilizador mostrando histórico de uso, consumo de créditos e performance de modelos estavam a martelar a nossa base de dados primária.
Solução: Read replica dedicada para todas as queries de analytics. O lag de replicação de 2 segundos é invisível para dashboards históricos.
Detalhe de implementação: Encaminhamos queries baseadas no endpoint. /api/analytics/* vai para a read replica; tudo o resto vai para a primária.
Padrão 3: Edge Caching para Respostas IA Estáticas
Algumas queries IA são surpreendentemente cacheáveis:
- Embeddings para o mesmo texto
- Classificações para inputs idênticos
- Traduções de frases idênticas
Implementámos uma cache semântica no edge (Cloudflare Workers KV):
- Hash do input + modelo + parâmetros relevantes
- Verificar cache antes de encaminhar para fornecedor
- Taxa de cache hit: 23% em todos os pedidos
- Poupámos aproximadamente €8.000/mês em custos de API
Estratégia de cache key:
const cacheKey = crypto.createHash('sha256')
.update(JSON.stringify({
model: request.model,
input: request.input,
temperature: request.temperature, // Apenas se determinístico (0)
// Excluir parâmetros que causam variação
}))
.digest('hex');
Monitorização e Observabilidade
Não consegues escalar o que não consegues ver. A nossa stack de observabilidade:
Métricas (Prometheus + Grafana):
- Taxa de pedidos por modelo, tenant e endpoint
- Percentis de latência (P50, P95, P99)
- Velocidade de consumo de créditos
- Health scores de fornecedores
Tracing (Jaeger):
- Traces de pedidos end-to-end
- Mapeamento de dependências cross-service
- Identificação de queries lentas
Alerting (PagerDuty):
- Taxa de erros excede 1% durante 5 minutos
- Latência P99 excede 10 segundos
- Falhas de escrita no sistema de créditos
- Circuit breaker de fornecedor abre
O incidente de Março teria sido apanhado 6 minutos mais cedo com a nossa monitorização atual. Isso são €20.000 poupados.
Lições Aprendidas
1. Desenha para o cliente 10x desde o primeiro dia. O cliente que nos derrubou não era malicioso—era bem-sucedido. Constrói rate limits, quotas de recursos e isolamento desde o início.
2. O modo de multi-tenancy deve ser atualizável. Os clientes crescem. O que começa como tenant de base de dados partilhada pode tornar-se cliente enterprise a precisar de isolamento. Planeia caminhos de migração.
3. Async por defeito, sync quando necessário. A maioria dos workloads IA não precisa de respostas em tempo real. Coloca-os em fila. A tua arquitetura vai agradecer.
4. Diversidade de fornecedores é uma feature, não um fardo. Quando a OpenAI cai, ter Anthropic e Google como fallbacks não é apenas fiabilidade—é vantagem competitiva.
5. Sistemas de créditos são sistemas financeiros. Trata-os com o rigor de um processador de pagamentos. Audit trails, reconciliação e deteção de anomalias são inegociáveis.
Construir uma plataforma que serve 100+ modelos IA em escala é fundamentalmente um problema de sistemas distribuídos com restrições específicas de IA. Os modelos são a parte fácil. A infraestrutura que os torna acessíveis, fiáveis e economicamente viáveis—é aí que a engenharia real acontece.