Amazon SAA-C03: Arquiteturas Serverless e Orientadas a Eventos / Integração de APIs — Guia de estudos
Faz parte do AWS SAA-C03 — Guia de estudos completo. Pratique com respostas verificadas no centro de exames da Amazon, ou faça testes cronometrados no ExamRoll.io.
AWS Lambda: Modelo de Execução, Ciclo de Vida do Runtime e Cold Starts
O Lambda executa código em micro-VMs Firecracker isoladas que seguem um ciclo de vida de duas fases. A fase INIT provisiona o contêiner, inicializa o runtime, baixa e descompacta o pacote de implantação e executa qualquer inicialização em nível de módulo — construção de clientes SDK, carregamento de segredos descriptografados com KMS, configuração de pool de conexões de banco de dados, carregamento de classes da JVM e aquecimento do JIT. A fase INVOKE executa o handler. Um cold start incorre no custo total da fase INIT; uma invocação “quente” (warm) reutiliza o ambiente, de modo que qualquer coisa armazenada em cache fora do handler (pools de keep-alive HTTP, segredos descriptografados, clientes de banco de dados) persiste entre as invocações naquele contêiner. É por isso que o padrão canônico é construir objetos caros no escopo do módulo e reutilizá-los:
import boto3, os
ddb = boto3.client('dynamodb') # reused across warm invokes
_secret = None
def _load_secret():
global _secret
if _secret is None:
_secret = kms.decrypt(...) # KMS call once per container, not per invoke
return _secret
def handler(event, ctx):
...
A magnitude do cold start varia de acordo com o runtime. Node.js e Python levam de dezenas a algumas centenas de milissegundos; a JVM e o .NET podem ultrapassar um segundo. Para funções anexadas a uma VPC, as ENIs do Hyperplane amortizaram em grande parte a penalidade histórica de anexação de ENI, mas o tamanho do pacote e o código pesado na fase INIT ainda dominam.
Três ferramentas abordam os cold starts de maneiras diferentes:
| Recurso | Comportamento | Custo | Melhor caso de uso |
|---|---|---|---|
| Simultaneidade sob demanda (On-demand concurrency) | Padrão; escala com um pico inicial de ~500–3.000 e depois +500/min | Por invocação + duração | Cargas de trabalho com picos (bursty) e tolerantes à latência |
| Simultaneidade provisionada (Provisioned concurrency) | Pré-inicializa N ambientes, com a fase INIT concluída antes do tráfego | Paga-se pelas unidades provisionadas 24/7 + invocações | SLA de latência p99 rigoroso |
| SnapStart (Java, Python, .NET) | Snapshot do Firecracker após a fase INIT; restaurado em um cold start | Sem custo extra para Java; pequena taxa de cache para os outros | Funções Java onde o provisionamento completo é um desperdício |
O SnapStart é a solução de melhor custo-benefício para cargas de trabalho Java sem contratos de latência rígidos — os cold starts caem em aproximadamente uma ordem de magnitude sem sobretaxa por invocação. A simultaneidade provisionada é a resposta correta quando uma API síncrona precisa manter um p99 abaixo de, digamos, 100 ms durante picos de tráfego; dimensioná-la para o pico p95 fecha a lacuna da latência de cauda (tail-latency). Subdimensioná-la é uma falha clássica: o modo sob demanda (on-demand) só inicia novos contêineres quando uma requisição chega, então um pico de tráfego produz esperas de vários segundos para os usuários reais.
# SAM: SnapStart on a Java 17 function
MyJavaFn:
Type: AWS::Serverless::Function
Properties:
Runtime: java17
SnapStart: { ApplyOn: PublishedVersions }
AutoPublishAlias: live
A própria simultaneidade provisionada pode ser escalada via Application Auto Scaling — uma ação agendada que aumenta de 10 para 200 às 07:45 e retorna ao valor anterior às 10:00 evita o pagamento por capacidade aquecida durante a noite, ao mesmo tempo que elimina os cold starts do pico da manhã.
O dimensionamento de memória é simultaneamente um controle de CPU: a vCPU escala linearmente com a memória até ~1.769 MB por vCPU. Uma função configurada com 128 MB pode custar mais no total do que uma com 1.024 MB, porque o tempo de execução dobrado muitas vezes excede o preço por milissegundo dobrado. Não adivinhe — use o AWS Lambda Power Tuning para varrer as configurações com cargas de trabalho representativas.
Controles de Simultaneidade do Lambda e Proteção de Sistemas Downstream
Três controles de simultaneidade são importantes e cada um tem uma função diferente:
- Simultaneidade reservada (Reserved concurrency) limita e reserva quantas execuções simultâneas uma função pode consumir. Ela separa uma parte da capacidade do pool da conta e protege sistemas downstream (uma pequena instância RDS, uma API de parceiro com limites de taxa) de serem sobrecarregados.
- Simultaneidade provisionada (Provisioned concurrency) pré-inicializa ambientes — é um controle de latência, não de escalabilidade.
- Simultaneidade não reservada da conta (Unreserved account concurrency) é o pool compartilhado, com um padrão de 1.000 por Região.
Assumir que o Lambda “escala infinitamente” ignora dois tetos. Primeiro, o limite de execuções simultâneas no nível da conta é real, e os limites de pico (burst) (inicial de 500–3.000 dependendo da Região, depois +500/min) governam a taxa de aumento. Uma vez excedido, chamadores síncronos recebem 429 TooManyRequestsException, que o API Gateway expõe como um erro 5xx. Segundo, os sistemas downstream têm seus próprios limites: uma instância db.t3.micro com max_connections=85 não consegue sobreviver a mil Lambdas simultâneos, cada um abrindo uma conexão. O PostgreSQL cria um processo de backend para cada conexão, consumindo ~10 MB de RAM; mesmo com CPU de sobra, apenas o estabelecimento e o encerramento da conexão podem sobrecarregar a instância.
As duas mitigações são (1) RDS Proxy, que agrupa e multiplexa muitas conexões do lado do cliente em um pequeno conjunto de conexões de backend persistentes, e (2) inserir uma fila para que a taxa de processamento seja desacoplada da taxa de chegada:
import psycopg2, os
conn = psycopg2.connect(
host=os.environ['PROXY_ENDPOINT'], # RDS Proxy, not the DB directly
dbname='orders', user='app', password=get_secret())
O RDS Proxy é uma solução de mudança mínima — o driver e a string de conexão mal mudam — o que o torna a resposta certa sempre que o requisito é “mínima alteração na aplicação” somado ao esgotamento de conexões. O DynamoDB não tem esse problema: sua API HTTPS é stateless, e é por isso que o DynamoDB combina naturalmente com cargas de trabalho Lambda de alto fan-out.
IAM, Variáveis de Ambiente e Rede do Lambda
Toda função assume uma role de execução na invocação. A política de confiança (trust policy) da role concede sts:AssumeRole para lambda.amazonaws.com; sua política de permissão (permission policy) define o que a função pode fazer. O runtime injeta credenciais STS de curta duração em AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY e AWS_SESSION_TOKEN automaticamente. Nunca incorpore chaves de acesso de usuário IAM em variáveis de ambiente ou no código — elas são estáticas, podem ser descobertas em código-fonte vazado ou exportações do CloudTrail, precisam ser rotacionadas manualmente e ignoram todo o modelo de credenciais temporárias.
FnRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal: { Service: lambda.amazonaws.com }
Action: sts:AssumeRole
Policies:
- PolicyName: ReadOrders
PolicyDocument:
Statement:
- Effect: Allow
Action: ["dynamodb:GetItem", "dynamodb:Query"]
Resource: !GetAtt OrdersTable.Arn
Variáveis de ambiente que contêm configurações sensíveis devem ser criptografadas com uma chave KMS gerenciada pelo cliente, usando “helpers para criptografia em trânsito” para que o console criptografe do lado do cliente. Descriptografe uma vez na fase INIT e armazene o texto puro em cache em uma variável em nível de módulo — caso contrário, cada invocação paga por uma chamada de API do KMS.
Por padrão, uma função é executada em uma VPC gerenciada pela AWS com saída irrestrita para a internet. Anexe-a à sua própria VPC somente quando ela precisar acessar recursos residentes na VPC (RDS em sub-redes privadas, ElastiCache, on-premise via Direct Connect). O Lambda então anexa ENIs Hyperplane nas sub-redes que você especificar e herda o roteamento delas.
A armadilha clássica é colocar uma função Lambda em uma sub-rede privada sem uma rota para o tráfego de serviços da AWS, exceto através de um NAT gateway — ou pior, uma instância NAT autogerenciada. Instâncias NAT saturam em uma única NIC, são um SPOF (ponto único de falha) e cobram por GB. Mesmo os NAT gateways cobram por GB e são desnecessários para o tráfego de serviços da AWS. O padrão correto é:
- Endpoints de VPC do tipo Gateway para S3 e DynamoDB (gratuitos)
- Endpoints de Interface (PrivateLink) para KMS, Secrets Manager, SQS, SNS, STS e similares
Isso mantém o tráfego na backbone da AWS, remove os limites de throughput do NAT e evita contas de egresso inesperadas. Note que as ENIs do Lambda nunca recebem um IP público; colocar a função em uma sub-rede “pública” não lhe dá acesso à internet — você ainda precisa de um NAT gateway em uma sub-rede pública separada com uma rota apropriada.
Amazon API Gateway: Tipos de Endpoint, Autorização e Entrega
O API Gateway oferece três tipos de API:
| Característica | REST API | HTTP API | WebSocket |
|---|---|---|---|
| Latência | Mais alta | ~60% menor | Stateful, bidirecional |
| Custo | Mais alto | ~70% mais barato | Por mensagem |
| Planos de uso / Chaves de API | Sim | Não | Não |
| Transformações de requisição/resposta (VTL) | Sim | Limitado | — |
| Autorizadores JWT | Via Lambda | Nativo | Via Lambda |
| WAF | Sim | Não (use CloudFront na frente) | Sim |
Escolha REST quando precisar de chaves de API e planos de uso, validação de requisição com JSON Schema, templates de mapeamento VTL, autorizadores Cognito com escopos por método ou WAF; escolha HTTP para padrões de proxy leves autenticados com JWT, onde custo e latência são mais importantes.
Os tipos de endpoint governam onde a API é exposta:
- Otimizado para a borda (Edge-optimized): exposta por uma distribuição CloudFront gerenciada pelo Gateway; o TLS é terminado no POP mais próximo. Ideal para clientes distribuídos globalmente.
- Regional: exposta a partir de uma única Região sem CloudFront. Ideal quando os clientes estão na mesma Região, quando você quer usar sua própria distribuição CloudFront na frente ou ao usar o roteamento baseado em latência do Route 53 entre múltiplas Regiões.
- Privado (Private): acessível apenas através de um endpoint de VPC de interface. Ideal para microsserviços internos que não devem atravessar a internet pública.
Selecionar “edge-optimized” para uma API interna de Região única adiciona um salto desnecessário do CloudFront e uma propagação de deploy mais lenta. Selecionar “regional” para uma API pública consumida globalmente força cada requisição a cruzar a internet pública até uma única Região.
Domínios personalizados exigem certificados ACM com uma localização que depende do tipo de endpoint: us-east-1 para “edge-optimized” (o CloudFront é global e termina o TLS lá); a própria Região da API para endpoints regionais. Confundir isso é um erro de configuração rotineiro. Mapeamentos de caminho base (base path mappings) permitem que um domínio multiplexe várias APIs (/orders → API de pedidos, /users → API de usuários).
A autorização tem quatro modelos, e ignorar as opções nativas é um antipadrão clássico:
| Mecanismo | Quando usar |
|---|---|
| Autorização IAM | Chamadores são AWS principals que podem assinar com SigV4 (outros serviços, SDKs, entre contas) |
| Autorizador de user pool do Cognito | Usuários se autenticam em um user pool do Cognito; o Gateway valida o JWT |
| Autorizador Lambda | Tokens não padrão, IdPs de terceiros sem OIDC, lógica complexa por requisição |
| Chaves de API + planos de uso | Medição, throttling, cotas — nunca use como autenticação |
Um autorizador Lambda personalizado adiciona uma invocação extra por requisição (ou por TTL do cache), outra função para aplicar patches e monitorar, e um caminho de código onde bugs na validação de assinatura podem permitir acesso silenciosamente. Use-o somente quando as opções nativas realmente não puderem atender ao requisito.
A integração de proxy com o Lambda é o padrão — a requisição inteira é passada como um evento e a função deve retornar a estrutura de envelope da resposta:
{
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": "{\"orderId\":\"abc123\"}",
"isBase64Encoded": false
}
Para ingestão do tipo “fire-and-forget” com TPS muito alto, use a integração direta do Gateway com serviços da AWS para enviar dados diretamente para o SQS ou Kinesis, pulando totalmente o salto do Lambda. Isso elimina cold starts no caminho de escrita e desacopla a taxa de ingestão da capacidade de processamento.
Para rollouts seguros, use canary deployments em um stage: uma porcentagem do tráfego vai para o novo deployment enquanto a maioria permanece na versão estável; métricas do CloudWatch por canary informam a promoção ou o rollback.
aws apigateway update-stage --rest-api-id abc123 --stage-name prod \
--patch-operations \
op=replace,path=/canarySettings/percentTraffic,value=10 \
op=replace,path=/canarySettings/deploymentId,value=xyz789
Para um webhook simples onde a cerimônia do API Gateway é excessiva (callback do Slack para um único tenant, handler de push do GitHub), as URLs de função do Lambda (Lambda function URLs) fornecem um endpoint HTTPS dedicado diretamente na função. Proteja-as com AuthType: AWS_IAM quando os chamadores forem AWS principals; se for NONE, você deve validar a assinatura da requisição dentro da função. Uma URL de função com AuthType: NONE e sem verificação na função é um endpoint de computação anônimo na internet pública.
Tipos de Invocação, Novas Tentativas e Idempotência
As fontes de eventos (event sources) se dividem em duas categorias com comportamentos muito diferentes. Fontes baseadas em push (API Gateway, ALB, S3, SNS, EventBridge, Cognito) invocam o Lambda diretamente e exigem uma política baseada em recurso (resource-based policy) do tipo AWS::Lambda::Permission que conceda a permissão lambda:InvokeFunction com o Principal correto (por exemplo, events.amazonaws.com) e o SourceArn. Sem ela, a regra corresponde aos eventos, mas cada invocação é silenciosamente negada — a função nunca é executada e as falhas aparecem apenas no CloudTrail. Isso é diferente da função de execução (execution role), que governa o que a função pode fazer, e não quem pode chamá-la.
Fontes baseadas em polling (SQS, Kinesis, DynamoDB Streams, MSK) são lidas pelo serviço Lambda por meio de um mapeamento de fonte de evento (event source mapping) — nenhuma política baseada em recurso é necessária, mas a função de execução deve conceder permissões de leitura.
Os tipos de invocação também ramificam o comportamento de novas tentativas:
- Síncrono (API Gateway, ALB, SDK com
RequestResponse): erros são retornados imediatamente; o chamador é responsável pelas novas tentativas. - Assíncrono (S3, SNS, EventBridge): o Lambda armazena em uma fila interna e tenta novamente duas vezes com atrasos em caso de falha, depois envia para uma DLQ (Fila de Mensagens Mortas) ou um destino em caso de falha (
on-failure destination). - Mapeamento de fonte de evento SQS: o SQS continua reenviando a mensagem até que o
maxReceiveCountacione a movimentação para a DLQ da fila de origem. - Kinesis / DynamoDB Streams: tenta novamente um único lote (
batch) de um shard até o sucesso ou a expiração, bloqueando o shard nesse ínterim — um lote travado paralisa todo o processamento downstream para aquela partição.
Como as novas tentativas estão embutidas em todas as camadas, a idempotência é obrigatória, não opcional. A expiração de um timeout de visibilidade do SQS durante uma escrita lenta ou uma nova tentativa assíncrona após um erro 5xx downstream produzirá duplicatas. O padrão canônico usa uma chave determinística e uma escrita condicional (conditional write) no DynamoDB:
def handler(event, context):
msg_id = event['Records'][0]['messageId']
try:
ddb.put_item(
TableName='processed',
Item={'id': {'S': msg_id}, 'ttl': {'N': str(ttl)}},
ConditionExpression='attribute_not_exists(id)')
except ddb.exceptions.ConditionalCheckFailedException:
return # already processed
process(event)
O decorator @idempotent do AWS Lambda Powertools implementa exatamente esse padrão, utilizando o DynamoDB como suporte.
Desacoplamento com SQS e SNS
Conectar fontes de push com alto fan-out diretamente ao Lambda é frágil. As notificações de eventos do S3, por exemplo, são síncronas por evento e estão sujeitas ao teto de concorrência do Lambda; se as invocações excederem a concorrência disponível durante um upload em massa (uma campanha de marketing que envia milhares de documentos em segundos), a janela de novas tentativas do S3 é curta e os eventos podem ser efetivamente descartados. A solução é usar um buffer:
| Padrão | Quando usar |
|---|---|
| S3 → Lambda direto | Taxa de eventos baixa e previsível; processamento idempotente |
| S3 → SQS → Lambda | Cargas de trabalho com picos; necessidade de novas tentativas/DLQ; limites de taxa downstream |
| S3 → SNS → múltiplos SQS | Fan-out para vários consumidores independentes |
| S3 → EventBridge → muitos alvos | Roteamento entre contas; filtragem baseada em conteúdo |
SNS é pub/sub: uma publicação, muitos assinantes (SQS, Lambda, HTTPS, e-mail). A filtragem de mensagens é baseada em atributos. SQS é uma fila ponto a ponto durável que retém mensagens por até 14 dias. A combinação principal é o fan-out SNS → SQS, que dá a cada consumidor sua própria fila com buffer para escalabilidade e reprodução (replay) independentes.
Para ordenação estrita (por exemplo, pedidos por cliente processados sequencialmente), use uma fila SQS FIFO com o MessageGroupId definido como a chave de ordenação. Mensagens dentro de um mesmo grupo são entregues em ordem; grupos diferentes são processados em paralelo. O SQS Standard oferece apenas ordenação de melhor esforço (best-effort).
O padrão canônico de ingestão desacoplada usa a integração direta do API Gateway com o SQS para absorver picos de tráfego e um processador com taxa limitada:
Resources:
OrdersQueue:
Type: AWS::SQS::Queue
Properties:
FifoQueue: true
ContentBasedDeduplication: true
RedrivePolicy:
deadLetterTargetArn: !GetAtt OrdersDLQ.Arn
maxReceiveCount: 5
ProcessorFunction:
Type: AWS::Lambda::Function
Properties:
ReservedConcurrentExecutions: 20 # cap the DB write rate
Mapping:
Type: AWS::Lambda::EventSourceMapping
Properties:
EventSourceArn: !GetAtt OrdersQueue.Arn
FunctionName: !Ref ProcessorFunction
BatchSize: 10
A concorrência reservada é deliberada — ela limita a velocidade com que o banco de dados recebe as escritas, de modo que a fila (e não o RDS) absorve o pico. Mensagens com falha são roteadas para uma DLQ após o maxReceiveCount para inspeção offline.
EventBridge: Regras, Transformação de Entrada e Destinos de API
O EventBridge é um barramento de eventos ciente de esquemas (schema-aware) com correspondência rica de padrões JSON, fontes de parceiros SaaS, registro de esquemas e funcionalidade de arquivamento/reprodução. As regras correspondem a padrões de eventos e fazem fan-out para mais de 30 tipos de alvos (targets) (Lambda, Step Functions, SQS, Kinesis, ECS, Firehose), com filtragem baseada no conteúdo do corpo da mensagem — não apenas em atributos como no SNS:
{
"source": ["tenant.energy"],
"detail-type": ["UsageReported"],
"detail": { "kWh": [{ "numeric": [">", 100] }] }
}
Uma regra pode ter até cinco alvos, cada um recebendo o evento bruto ou um subconjunto transformado. Transformadores de entrada (Input transformers) impõem o acoplamento fraco: um InputPathsMap extrai caminhos JSON do evento, e um InputTemplate os remodela para o formato exato que o alvo espera:
EventPattern:
source: ["com.acme.orders"]
detail-type: ["OrderPlaced"]
Targets:
- Arn: !GetAtt PaymentValidator.Arn
InputTransformer:
InputPathsMap:
orderId: "$.detail.orderId"
amount: "$.detail.total"
card: "$.detail.payment.cardToken"
InputTemplate: |
{"orderId": <orderId>, "amount": <amount>, "cardToken": <card>}
Cada Lambda de validação recebe apenas o que precisa; o validador de endereço nunca vê o token do cartão. Isso é decisivamente superior a uma função Lambda monolítica que recebe o evento completo e se ramifica internamente — um monólito concentra as permissões do IAM (uma única role precisa ter todas as permissões downstream), aumenta o raio de impacto (blast radius) de um bug, acopla a cadência de implantação, impede o ajuste de memória/timeout por responsabilidade e força a função inteira a escalar com base na taxa do ramo de maior volume.
Destinos de API (API destinations) invertem a direção: o EventBridge chama um endpoint HTTPS externo. Combinado com uma conexão (connection) que armazena credenciais do tipo Basic, chave de API ou OAuth no Secrets Manager, esta é a maneira serverless de notificar um SaaS de terceiros quando, por exemplo, um job do AWS Batch é concluído com sucesso — sem a necessidade de uma função Lambda. O EventBridge captura o evento de mudança de estado, uma regra corresponde a JobSucceeded, e o alvo do tipo destino de API faz um POST para o fornecedor com as credenciais injetadas a partir da conexão.
Regras agendadas (expressões cron/rate) ou o mais novo EventBridge Scheduler substituem instâncias EC2 de heartbeat para tarefas periódicas — relatórios noturnos, atualização de cache a cada hora.
Escolha o EventBridge em vez do SNS quando a filtragem for baseada no conteúdo do corpo da mensagem (não apenas em atributos), quando novos consumidores precisarem se conectar posteriormente sem alterações no produtor, ou quando o roteamento abranger múltiplas contas ou fontes SaaS. Escolha o SNS quando o fan-out for uma simples notificação filtrada por atributos para um conjunto estável de assinantes.
Step Functions: Orquestração e Distributed Map
Quando um fluxo de trabalho (workflow) tem mais do que alguns passos, ramificações (branching), tentativas (retries), aprovação humana ou esperas longas, incorporar essa lógica em Lambdas encadeadas se torna insustentável. O Step Functions externaliza a máquina de estados (state machine) na Amazon States Language.
- Workflows Standard: até um ano, semântica exactly-once (exatamente uma vez), histórico de execução completo,
.waitForTaskTokenpara portões (gates) humanos/externos. Atendimento de pedidos, ETL, fluxos de aprovação. - Workflows Express: até cinco minutos, at-least-once (pelo menos uma vez), alto volume, baixo custo por execução. Orquestrações síncronas curtas por trás do API Gateway; transformações de IoT e streaming.
Toda tarefa (task) deve declarar Retry e Catch explícitos:
"ValidatePayment": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {"FunctionName": "PaymentValidator", "Payload.$": "$"},
"Retry": [{
"ErrorEquals": ["Lambda.ServiceException", "Lambda.TooManyRequestsException"],
"IntervalSeconds": 2, "MaxAttempts": 4, "BackoffRate": 2.0
}],
"Catch": [{"ErrorEquals": ["PaymentDeclined"], "Next": "RefundStep"}],
"Next": "ShipOrder"
}
Os estados Parallel e Map executam ramificações (branches) concorrentemente e agregam os resultados — um encaixe perfeito para sistemas de pedidos com validadores independentes (endereço, inventário, pagamento). O estado entre os passos flui através do documento JSON da execução, eliminando a necessidade de um banco de dados compartilhado usado apenas para a coordenação do fluxo de trabalho.
O padrão .waitForTaskToken pausa a execução até que um ator externo chame SendTaskSuccess com o token — a resposta canônica quando um fluxo de trabalho abrange Lambdas, EC2, contêineres, sistemas on-premise e requer aprovação manual com sobrecarga operacional (ops overhead) mínima:
"ManagerApproval": {
"Type": "Task",
"Resource": "arn:aws:states:::sns:publish.waitForTaskToken",
"Parameters": {
"TopicArn": "arn:aws:sns:us-east-1:111:approvals",
"Message": { "TaskToken.$": "$$.Task.Token", "OrderId.$": "$.orderId" }
},
"Next": "Fulfill"
}
O Distributed Map estende o estado Map padrão para processar até 10.000 execuções filhas (child executions) paralelas e pode iterar diretamente sobre objetos em um bucket S3 ou linhas em um arquivo CSV/JSONL, com loteamento (batching), checkpointing e tolerância a falhas automáticos. Para milhares de objetos S3 semiestruturados, é a opção mais eficiente operacionalmente — aponte-o para um prefixo, defina a tarefa por item, e o Step Functions cuida do fan-out, MaxConcurrency, tentativas (retries) e agregação de resultados:
{
"Type": "Map",
"ItemReader": {
"Resource": "arn:aws:states:::s3:listObjectsV2",
"Parameters": { "Bucket": "raw-events", "Prefix": "2024/" }
},
"MaxConcurrency": 1000,
"ItemProcessor": {
"ProcessorConfig": { "Mode": "DISTRIBUTED", "ExecutionType": "STANDARD" },
"StartAt": "ProcessObject",
"States": { "ProcessObject": { "Type": "Task", "Resource": "arn:aws:lambda:...:function:ProcessOne", "End": true } }
}
}
Recriar o mesmo no SQS ou EventBridge exige uma contabilidade personalizada para conclusão, tentativas (retries) e montagem de resultados.
Step Functions vs. EventBridge: O Step Functions é a escolha certa quando você é dono da sequência e do resultado — estado, ramificações, tentativas, aprovações. O EventBridge é a escolha certa quando os produtores (producers) não sabem ou não se importam com quem consome, e os consumidores (consumers) se anexam de forma independente.
Notificações de Eventos do S3
Para processamento de uploads quase em tempo real (near-real-time), configure notificações de eventos do S3 em s3:ObjectCreated:* (ou uma variante específica como Put, Post, CompleteMultipartUpload) com um alvo (target) Lambda — sujeito às ressalvas de burst mencionadas acima. Mecanismos de proteção (Guardrails):
- Defina concorrência reservada (reserved concurrency) para proteger um banco de dados downstream.
- Habilite uma DLQ ou um destino em caso de falha (on-failure destination) para mensagens “poison” (poison messages).
- Roteie eventos do S3 através do EventBridge quando múltiplos consumidores precisam dos mesmos eventos. As configurações de notificação direta do S3 são limitadas em quantidade e expressividade; o fan-out do EventBridge com transformadores de entrada (input transformers) por alvo escala muito melhor.
Streaming: Kinesis Data Streams vs. Firehose
O Kinesis Data Streams (KDS) é um log particionado (sharded), ordenado e reproduzível (replayable) com retenção de 24 horas a 365 dias. A ordem é preservada por shard, com base na chave de partição (partition key) — crucial para agregação por dispositivo ou por tenant. Múltiplos consumidores leem de forma independente (enhanced fan-out para throughput isolado por consumidor). Escolha o KDS quando precisar de reprodução ordenada, múltiplos consumidores independentes ou alto throughput por shard.
O Kinesis Data Firehose é um fluxo de entrega (delivery stream) totalmente gerenciado para S3, Redshift, OpenSearch ou Splunk com buffer embutido (60 s ou 1–128 MB), transformação opcional com Lambda, compressão (GZIP, Snappy) e conversão para Parquet/ORC. Sem shards para gerenciar. O Firehose é a escolha de baixa sobrecarga operacional (low-ops) quando consumidores personalizados e reprodução (replay) não são necessários — apenas para depositar dados quase em tempo real.
O pipeline canônico de análise quase em tempo real é produtores (producers) → KDS → Firehose → S3 (Parquet) → Athena/QuickSight, com enriquecimento opcional via Lambda no Firehose.
AWS Transfer Family para SFTP Gerenciado
Quando parceiros exigem SFTP, FTPS ou FTP para dentro ou para fora do S3 ou EFS, o AWS Transfer Family fornece um endpoint gerenciado e multi-AZ que fala o protocolo que os clientes já usam. A autenticação suporta usuários gerenciados pelo serviço, chaves SSH ou IdPs personalizados via API Gateway/Lambda. Os arquivos são depositados diretamente no S3 com SSE e políticas de ciclo de vida (lifecycle policies) aplicadas; políticas de IAM com escopo reduzido (scope-down policies) restringem cada usuário a um prefixo específico.
Construir isso por conta própria no EC2 exige hardening do OpenSSH, aplicação de patches, alta disponibilidade (HA) entre AZs, rotação de chaves e envio de logs (log shipping) — tudo o que o Transfer Family absorve. Escolha-o sempre que o requisito for “parceiros nos enviam arquivos por SFTP” e você quiser os arquivos no S3 com o mínimo de sobrecarga operacional.
Compondo um Padrão Serverless Canônico
Um design de ingestão de baixa sobrecarga (low-overhead) para métricas horárias por tenant: sensores fazem POST para o API Gateway (HTTP API, regional) → Lambda valida e publica no EventBridge → regras roteiam para um Lambda que escreve no DynamoDB (ID do tenant como chave de partição, bucket de hora como chave de ordenação) e, em paralelo, para o Firehose → S3 (Parquet) para análise. Novos consumidores se anexam como regras adicionais do EventBridge sem tocar nos produtores — o requisito de extensibilidade que o SNS sozinho não atenderia tão bem. Onde throughput sustentado e ordenação são importantes (reconciliação de faturamento, fluxos de eventos financeiros), substitua o EventBridge pelo Kinesis Data Streams e use o enhanced fan-out para consumidores independentes.
Catálogo de Armadilhas: Por que os Padrões Errados Mais Comuns Falham
Instância/gateway NAT para tráfego de serviços da AWS a partir de Lambdas em sub-redes privadas. Instâncias NAT limitam a vazão (throughput) à NIC de uma única EC2 e são um SPOF (Ponto Único de Falha); gateways NAT cobram por GB. Ambos são desnecessários para destinos de serviços da AWS. Use endpoints de gateway para S3/DynamoDB e endpoints de interface para todo o resto.
Ignorar cold starts em APIs críticas de latência. O modo sob demanda (on-demand) só provisiona contêineres quando uma requisição chega, então picos de tráfego (bursts) não atendem aos SLAs. Dimensione a concorrência provisionada para o p95 dos picos de tráfego; use o SnapStart para cargas de trabalho Java sem SLAs rígidos.
Lambda monolítica que recebe um evento completo e faz o roteamento internamente. Viola o princípio do menor privilégio (uma única role detém todas as permissões downstream), acopla a cadência de deployment, impede o ajuste fino por responsabilidade e escala a função inteira com base na taxa do ramo mais ruidoso. Divida por responsabilidade; conecte as partes com EventBridge ou Step Functions.
Conexões diretas com o banco de dados a partir de muitas Lambdas. O total de conexões é igual às invocações concorrentes porque os contêineres não compartilham pools. Corrija com o RDS Proxy (pooling), concorrência reservada (limite de taxa) ou SQS (buffering).
Lambda síncrona para ingestão em picos de tráfego (bursty). Exceder a concorrência retorna 429 para o API Gateway e 5xx para os clientes; notificações diretas do S3 durante picos de tráfego descartam eventos silenciosamente. Insira o SQS no fluxo ou use a integração direta do Gateway → SQS.
URLs de função Lambda públicas com AuthType: NONE e sem validação de assinatura na função. Computação anônima na internet pública. Use AWS_IAM para chamadores da AWS ou valide assinaturas para webhooks de terceiros.
Authorizer Lambda customizado onde um integrado funcionaria. Adiciona latência, outra função para aplicar patches e um caminho de código onde bugs na verificação de assinatura permitem acesso silenciosamente. Prefira a autorização IAM para principals da AWS; authorizer do Cognito para user pools.
Região incorreta do certificado ACM para domínios customizados. Endpoints otimizados para a borda (edge-optimized) exigem o certificado em us-east-1; endpoints regionais exigem na própria Região da API.
Falta de AWS::Lambda::Permission para fontes de eventos push (EventBridge, S3, SNS). Os eventos correspondem às regras, mas as invocações são negadas silenciosamente. Diferente da execution role — isso governa quem pode chamar a função, não o que a função pode fazer.
Falta de idempotência. Toda camada faz novas tentativas (retries) — invocações assíncronas, reentrega do SQS na expiração do visibility timeout, novas tentativas de lote (batch) do Kinesis. Sem uma chave de desduplicação determinística e uma escrita condicional, os duplicados são inevitáveis.
← Contêineres e Orquestração · Todos os domínios · Armazenamento e Ciclo de Vida de Dados →
Pratique estas questões → · Prática cronometrada no ExamRoll.io →
Pass the whole exam — not just this question
You found this answer. Get every verified question and explanation in one place, and save hours of prep. Free to start.
Passe no seu exame →