Serverless: funções como serviço e seus trade-offs
1. Introdução ao Serverless e FaaS
No contexto da Arquitetura de Software, o termo Serverless não significa ausência de servidores, mas sim a abstração completa do gerenciamento de infraestrutura. O desenvolvedor se concentra exclusivamente no código da aplicação, enquanto o provedor de nuvem provisiona, escala e mantém os servidores automaticamente.
Functions as a Service (FaaS) é a materialização mais pura desse paradigma. Diferentemente do PaaS (Platform as a Service), onde você gerencia o ambiente de execução da aplicação, e do IaaS (Infrastructure as a Service), onde gerencia máquinas virtuais, no FaaS você envia funções individuais que são executadas sob demanda. Cada função é um bloco de código autônomo, stateless e efêmero.
Os principais provedores incluem:
- AWS Lambda: pioneiro, integração profunda com ecossistema AWS
- Azure Functions: forte integração com serviços Microsoft
- Google Cloud Functions: foco em simplicidade e integração com GCP
2. Modelo de Execução e Ciclo de Vida
No FaaS, a execução é orientada a eventos. Quando um acionador ocorre, o provedor aloca um contêiner, carrega o runtime e executa a função. Esse processo revela dois estados críticos:
- Cold start: ocorre quando um novo contêiner precisa ser iniciado. Pode adicionar latência de 100ms a vários segundos, dependendo do runtime e do tamanho do pacote.
- Warm start: quando o contêiner já está ativo e reutilizado para invocações subsequentes, reduzindo drasticamente a latência.
Exemplo de função simples em Node.js:
exports.handler = async (event) => {
const name = event.queryStringParameters?.name || 'Mundo';
return {
statusCode: 200,
body: `Olá, ${name}!`
};
};
Limitações importantes:
- Tempo máximo de execução: tipicamente 15 minutos (AWS Lambda)
- Memória: de 128 MB a 10 GB
- Armazenamento temporário: /tmp limitado a 512 MB a 10 GB
3. Arquitetura Orientada a Eventos no Serverless
A natureza event-driven do FaaS permite padrões arquiteturais poderosos:
Acionadores comuns:
- HTTP (API Gateway)
- Filas (SQS, RabbitMQ)
- Bancos de dados (DynamoDB Streams, CDC)
- Storage (S3 uploads)
Padrões de composição:
Fan-out (processamento paralelo):
Função A recebe evento -> publica 100 mensagens no SQS
Função B processa cada mensagem independentemente
Fan-in (agregação de resultados):
Múltiplas funções gravam resultados parciais no DynamoDB
Função C é acionada quando todos os resultados estão prontos
Para orquestração complexa, serviços como AWS Step Functions ou Azure Durable Functions são recomendados, pois evitam acoplamento excessivo entre funções.
4. Trade-offs de Desempenho e Latência
O cold start é o principal vilão do desempenho em FaaS. Seu impacto varia:
- Runtimes: Java e .NET sofrem mais (500ms-5s); Python e Node.js são mais rápidos (100ms-1s)
- Tamanho do pacote: bibliotecas pesadas aumentam o tempo de carregamento
- VPC: funções dentro de VPC têm cold starts mais longos devido à alocação de ENI
Estratégias de mitigação:
- Provisioned Concurrency (AWS): mantém N instâncias sempre aquecidas
- Warmers: funções heartbeat que invocam a função periodicamente
- Redução de dependências: minimize bibliotecas e use layers otimizados
Throttling: provedores impõem limites de concorrência (ex: 1000 execuções simultâneas por região no Lambda). Exceder resulta em erros 429.
5. Gerenciamento de Estado e Dados
Funções são inerentemente stateless – cada invocação é isolada. Estado compartilhado exige serviços externos:
Padrões de armazenamento:
- DynamoDB: baixa latência, escalável, ideal para sessões
- Redis (ElastiCache): cache distribuído para dados temporários
- S3: armazenamento de objetos para arquivos grandes
Exemplo de função com estado externo:
const AWS = require('aws-sdk');
const dynamo = new AWS.DynamoDB.DocumentClient();
exports.handler = async (event) => {
const params = {
TableName: 'sessions',
Key: { sessionId: event.sessionId }
};
const result = await dynamo.get(params).promise();
return { statusCode: 200, body: JSON.stringify(result.Item) };
};
Desafios: transações distribuídas e consistência eventual exigem padrões como Saga ou compensação manual.
6. Custos e Modelos de Precificação
O modelo pay-per-use é a maior vantagem do FaaS para cargas esporádicas. Você paga por:
- Número de requisições
- Tempo de execução (arredondado para 100ms)
- Memória alocada
Custos ocultos:
- Cold starts: invocações extras para manter funções aquecidas
- Transferência de dados entre regiões
- Logs no CloudWatch (retenção e volume)
- API Gateway (custo por requisição)
Comparação TCO:
- Para workloads previsíveis (ex: 24/7), instâncias reservadas ou contêineres podem ser 40-60% mais baratos
- Para cargas variáveis (ex: picos sazonais), FaaS reduz drasticamente o custo
7. Observabilidade e Depuração
Ambientes efêmeros dificultam debugging tradicional. Ferramentas essenciais:
- CloudWatch Logs: logs centralizados, mas sem contexto de execução
- AWS X-Ray: tracing distribuído, identifica gargalos entre funções
- OpenTelemetry: padrão aberto para instrumentação multi-provedor
Estratégias de teste:
- Testes locais com ferramentas como SAM CLI (AWS) ou Functions Framework (Google)
- Ambientes de staging idênticos à produção
- Logs estruturados em JSON para facilitar consultas
8. Quando Usar (e Quando Evitar) Serverless
Casos de uso ideais:
- Webhooks e processamento de eventos assíncronos
- APIs com tráfego variável (ex: CRUD leve)
- Processamento de streams (Kinesis, Kafka)
- Transformação de dados em pipelines ETL
- Tarefas agendadas (cron jobs)
Anti-padrões:
- Jobs de longa duração (>15 minutos)
- Workloads intensivos em CPU (processamento de vídeo, ML training)
- Aplicações com estado de conexão persistente (WebSockets)
- Sistemas que exigem latência consistente <10ms
Decisão arquitetural: a abordagem mais madura é combinar Serverless com microsserviços tradicionais. Use FaaS para componentes event-driven e escaláveis, enquanto mantém serviços stateful ou de longa duração em contêineres ou VMs.
Conclusão
Serverless e FaaS representam uma evolução significativa na Arquitetura de Software, oferecendo escalabilidade automática e redução de custos operacionais. No entanto, os trade-offs de latência, estado e observabilidade exigem análise cuidadosa. O sucesso depende de alinhar o padrão arquitetural ao tipo de workload, combinando diferentes abordagens quando necessário.
Referências
- AWS Lambda Documentation — Documentação oficial da AWS Lambda, incluindo limites, boas práticas e exemplos de código
- Azure Functions Overview — Guia completo sobre Azure Functions, planos de hospedagem e integrações
- Google Cloud Functions Documentation — Documentação oficial do Google Cloud Functions com tutoriais e padrões de arquitetura
- Serverless Architectures on AWS — Página oficial da AWS sobre arquiteturas serverless, whitepapers e casos de uso
- Martin Fowler: Serverless Architectures — Artigo técnico aprofundado sobre trade-offs, padrões e anti-padrões de serverless
- OpenTelemetry Serverless Instrumentation — Guia oficial para instrumentação de funções serverless com OpenTelemetry
- AWS Well-Architected Serverless Lens — Práticas recomendadas para arquiteturas serverless no contexto do Well-Architected Framework