Serviços que somam ao Bedrock V: compute, orquestração e estado
- ⬜🔌 Serviços que somam ao Bedrock IV: canais e borda(AWS Bedrock — GenAI em Produção)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
Duas características desta camada definem mais decisões de arquitetura do que qualquer preferência de stack: o teto de execução da função serverless e o fato de que fila e barramento entregam a mensagem ao menos uma vez. A primeira derruba agents que investigam por muito tempo; a segunda produz pedido duplicado no ERP se ninguém tratou. Nenhuma das duas é opinião — são propriedades do sistema, e projetar contra elas é o que separa pipeline que sobrevive a pico de pipeline que gera incidente. Este módulo percorre os 17 serviços de compute, orquestração e estado.
Como escolher nesta camada
- Quanto tempo o trabalho leva? Segundos cabem em qualquer lugar. Minutos derrubam a função serverless. Horas exigem orquestração com estado durável.
- Quem decide o próximo passo — seu código ou o modelo? Código é workflow, com custo previsível e etapa testável. Modelo é agent, com autonomia paga em variabilidade.
- Precisa lembrar do que aconteceu antes? Sem estado, tudo fica mais simples. Com estado, você decide onde ele mora, por quanto tempo vive e quanto do histórico volta no contexto.
A regra que resolve a maior parte das dúvidas
Síncrono e curto: função. Assíncrono e curto: evento com fila. Assíncrono e longo: máquina de estados. Longo, com estado e autônomo: runtime de agent. Comece pelo mais simples que resolve e suba um degrau só quando um limite concreto empurrar — subir por antecipação é como se paga complexidade sem receber nada.
Compute: onde o código roda
| Serviço | O que é | O que soma ao Bedrock | O limite que decide |
|---|---|---|---|
| AWS Lambda | Função gerenciada que escala do zero e cobra por execução | A cola padrão de arquitetura de IA na AWS: gateway, orquestração curta, consumidor de fila, tratamento de tool | Teto de 15 minutos de execução e nenhum estado entre invocações |
| ECS / Fargate | Container gerenciado, sem servidor para operar | Laço de agent que ultrapassa o teto da função, ou serviço que mantém conexão persistente aberta | Você paga capacidade enquanto a tarefa vive, ocupada ou não; escalar do zero é mais lento |
| Amazon EKS | Kubernetes gerenciado | Só faz sentido quando a empresa já padronizou a plataforma inteira em Kubernetes | Complexidade operacional que não se justifica pela carga de IA isolada |
| Amazon EC2 | Máquina virtual com controle total | GPU própria para modelo auto-hospedado, ou requisito de isolamento que nenhum gerenciado atende | Você opera tudo: patch, escala, GPU parada custando por hora |
| AWS Batch | Execução de lote em larga escala com fila de jobs | Processamento massivo fora do modo batch do Bedrock — pré-processamento de mídia, por exemplo | Não é para carga interativa; a fila introduz espera por natureza |
| AgentCore Runtime | Runtime gerenciado para sessão de agent, isolada e de longa duração | Sessão que atravessa muitos turnos, com memória e observabilidade próprias, sem você operar container | Mais peças para observar e custear; monitore custo por sessão desde o começo |
O teto de 15 minutos e as três saídas
Um agent investigando um problema pode ultrapassar o limite de execução da Lambda. As saídas, em ordem de simplicidade: (1) quebrar em passos e deixar o Step Functions coordenar, mantendo cada Lambda curta — resolve a maioria dos casos e ainda dá retry por passo; (2) mover o laço para Fargate, que não tem esse teto; (3) usar AgentCore Runtime, feito para sessão longa. Aumentar memória para acelerar não resolve: o teto é de tempo, não de recurso.
Container ou runtime de agent?
Os dois resolvem o teto de execução, e a escolha é sobre o que você quer operar. Container dá controle total e obriga você a construir memória, isolamento por usuário e observabilidade de trajetória — que é justamente o que o runtime de agent entrega pronto. Se o laço é simples e você já opera containers, container. Se o agent precisa lembrar entre sessões e você quer a trajetória visível sem instrumentar, runtime de agent.
Orquestração: quem coordena os passos
| Serviço | O que é | O que soma ao Bedrock | O limite que decide |
|---|---|---|---|
| Step Functions (Standard) | Máquina de estados com execução durável, retry por passo e histórico completo | Pipeline longo, ramo que espera decisão humana por horas ou dias, e trilha auditável passo a passo | Cobra por transição de estado: laço muito granular fica caro rápido |
| Step Functions (Express) | Modo de alto volume e curta duração, muito mais barato por execução | Orquestração de segundos disparada com altíssima frequência | Duração limitada e histórico diferente do modo padrão — não serve para ramo humano |
| Bedrock Flows | Orquestração visual de fluxo de GenAI, com prompts versionados | Quando quem mantém o fluxo não é o time de engenharia | Menos expressivo que código quando a lógica cresce; migrar depois é reescrever |
📋 Processar 40 mil documentos por mês que chegam ao longo do dia, com extração pelo modelo, validação, revisão humana quando necessário e gravação no sistema de origem.
O caminho comum é curto e cabe folgado na Lambda — usar orquestração pesada em cada documento pagaria transição de estado sem necessidade. O Step Functions entra apenas no ramo que espera decisão humana, que pode levar horas ou dias e precisa de estado durável e trilha auditável.
Alt: Step Functions para todo documento — Auditabilidade excelente, custo de transição desnecessário em dezenas de milhares de execuções simples por mês.
Alt: Só Lambda com polling na fila — Funciona, mas sem o roteamento por regra você acopla origem e destino e perde a flexibilidade de plugar novos consumidores.
Alt: Tudo em batch noturno — Mais barato por documento, e o tempo de ciclo passa a ser de até um dia — inaceitável quando o documento destrava um atendimento.
Transição de estado é a unidade de cobrança — e a de desperdício
O modo padrão cobra por transição, então uma máquina de estados com muitos passos pequenos para cada item de um lote grande fica surpreendentemente caro. O desenho que costuma funcionar: orquestração para o fluxo macro e para o ramo que espera humano, e função única cuidando da sequência curta de dentro. Se o seu diagrama de estados tem mais caixas de encanamento do que de negócio, provavelmente esse recorte está errado.
Eventos e filas: o que protege do pico
| Serviço | O que é | O que soma ao Bedrock | O limite que decide |
|---|---|---|---|
| Amazon EventBridge | Barramento que roteia eventos por regra, desacoplando produtor e consumidor | Reagir a fatos: arquivo chegou, ticket abriu, cadastro mudou — sem o produtor conhecer quem consome | Entrega ao menos uma vez: o consumidor precisa ser idempotente, sem exceção |
| EventBridge Pipes | Ligação direta entre origem e destino, com filtro e transformação leve | Mover evento entre serviços sem escrever função de cola só para repassar | Transformação limitada; lógica de verdade continua sendo código |
| EventBridge Scheduler | Agendamento gerenciado, único ou recorrente | Dispara a avaliação diária de amostra, o reprocessamento e o relatório de custo | É gatilho, não orquestrador: o que roda depois é problema seu |
| Amazon SQS | Fila com buffer, tempo de invisibilidade, retry e fila de mensagens mortas | É o que protege você do throttling do modelo quando mil arquivos chegam de uma vez | Invisibilidade menor que o processamento reprocessa a mensagem — e você paga a inferência duas vezes |
| Amazon SNS | Publicação para muitos assinantes ao mesmo tempo | Notificar vários sistemas do mesmo fato, em leque | Sem buffer: assinante fora do ar perde a mensagem. Combine com fila para durabilidade |
Os três erros clássicos deste desenho
Primeiro: tempo de invisibilidade da fila menor que o tempo de processamento — a mensagem reaparece enquanto ainda está sendo processada, e você paga a inferência duas vezes e grava dois registros. Segundo: consumidor não idempotente, com entrega ao menos uma vez do outro lado, o que produz duplicata em qualquer pico. Terceiro: ausência de fila de mensagens mortas, que transforma um documento problemático num laço eterno de retry pago.
A fila é a peça que mais barato compra tranquilidade
Carga de IA tem duas características que fazem a fila valer mais do que numa API comum: a inferência tem quota por região, e cada retry custa dinheiro de verdade. A fila absorve o pico sem estourar a quota, espaça as tentativas em vez de bater na parede, e isola numa fila separada o item que falha sempre — em vez de deixá-lo girando e cobrando. São poucas linhas de configuração para eliminar a classe de incidente mais comum do pipeline assíncrono.
Num pipeline de documentos com fila, alguns arquivos geram dois registros no sistema de destino. O código não tem bug aparente. O que investigar primeiro?
Onde mora o estado da conversa
| Serviço | O que é | O que soma ao Bedrock | O limite que decide |
|---|---|---|---|
| Amazon DynamoDB | Banco de chave-valor com latência de milissegundos e expiração automática de item | Histórico da conversa, registro de conexão, controle de idempotência e rastreio por documento | Modele pela consulta; item tem teto de tamanho, então histórico longo vai para o S3 |
| ElastiCache / MemoryDB | Cache em memória compartilhado, muito rápido | Cache semântico, contador de quota por app e sessão quente do gateway | Cobra capacidade provisionada, ocupada ou não — não é o primeiro passo |
| Aurora Serverless | Relacional com transação, escalando por demanda | Quando o estado do assistente precisa conviver com o dado transacional que já existe | Latência maior que chave-valor no acesso simples; conexão precisa de pool |
| AgentCore Memory | Memória gerenciada de curto e longo prazo, isolada por ator | Agent que precisa lembrar entre sessões sem você construir e operar isso | Mais uma peça para observar e custear; o isolamento por ator é responsabilidade sua na modelagem |
import time, boto3
from boto3.dynamodb.conditions import Key
tb = boto3.resource("dynamodb").Table("conversas")
JANELA = 12 # turnos mantidos no contexto quente
TTL_DIAS = 30
def salvar_turno(sessao, papel, texto, uso=None):
agora = int(time.time())
tb.put_item(Item={
"pk": f"sessao#{sessao}",
"sk": f"turno#{agora}#{papel}",
"papel": papel,
"texto": texto,
"tokens_entrada": (uso or {}).get("inputTokens", 0),
"tokens_saida": (uso or {}).get("outputTokens", 0),
"cache_lido": (uso or {}).get("cacheReadInputTokens", 0),
# Expiracao automatica: sem isto a tabela cresce para sempre e
# voce guarda dado pessoal alem do que a politica de retencao permite.
"ttl": agora + TTL_DIAS * 86400,
})
def carregar_historico(sessao):
# Janela deslizante: o custo por turno cresce com o historico reenviado,
# entao NAO carregue a conversa inteira "por seguranca".
r = tb.query(
KeyConditionExpression=Key("pk").eq(f"sessao#{sessao}")
& Key("sk").begins_with("turno#"),
ScanIndexForward=False,
Limit=JANELA,
)
itens = sorted(r["Items"], key=lambda i: i["sk"])
return [{"role": i["papel"], "content": [{"text": i["texto"]}]} for i in itens]
def ja_processado(chave: str) -> bool:
"""Idempotencia: entrega ao menos uma vez e retry sao normais."""
try:
tb.put_item(
Item={"pk": f"idem#{chave}", "sk": "lock",
"ttl": int(time.time()) + 86400},
ConditionExpression="attribute_not_exists(pk)",
)
return False
except tb.meta.client.exceptions.ConditionalCheckFailedException:
return True
Histórico infinito é bug de custo
Mandar a conversa inteira em todo turno faz o custo crescer mais que linearmente: o turno 30 paga os 29 anteriores de novo. Janela deslizante resolve a maior parte dos casos; onde o fio precisa sobreviver, use compactação. E lembre que histórico guardado é dado pessoal armazenado — expiração automática não é higiene de banco, é requisito de privacidade.
Estado de conversa é dado pessoal armazenado
A tabela de conversas guarda o que o usuário escreveu — e frequentemente dado que ele não deveria ter escrito. Expiração automática de item não é higiene de banco nesse contexto: é o mecanismo que implementa a política de retenção. Defina o prazo com o encarregado de dados antes de o primeiro turno ser gravado, porque descobrir depois que existem dois anos de conversa sem política é um problema de conformidade, não de armazenamento.
- → evento de criação de objeto
- → fila protege do throttling do modelo
- → já processei esta chave? se sim, encerra
- → inferência só depois da checagem
- → ramo humano precisa de estado durável
- → laço longo migra para container
- Armazenamento
- Integração de apps
- Compute
- IA e machine learning
- Banco de dados
As duas peças que evitam incidente estão nos passos 2 e 3: a fila absorve o pico e a checagem de idempotência impede que a entrega ao-menos-uma-vez gere registro duplicado.
- O fato acontece. Arquivo no S3 ou rotina agendada. Nada de polling: o evento é a origem, e o produtor não conhece o consumidor.
- A fila absorve o pico. Mil arquivos de uma vez não viram mil chamadas simultâneas ao modelo. A fila espaça, e a fila de mensagens mortas isola o que falha sempre.
- Idempotência antes de qualquer efeito. Entrega ao-menos-uma-vez é comportamento esperado, não anomalia. A checagem por chave vem antes da inferência — senão você paga duas vezes e grava dois registros.
- Inferência. Só o que chegou até aqui e não foi processado antes consome token.
- O ramo que espera humano. Revisão pode levar horas ou dias: isso exige estado durável e trilha auditável, não uma função esperando.
- Quando o laço não cabe. Agent que ultrapassa o teto de execução migra para container — ou quebra em passos coordenados, que é a saída mais simples.
Combinações que se repetem
| Borda | Compute | Orquestração | Estado | |
|---|---|---|---|---|
| Chat com streaming | API Gateway WebSocket | Lambda com ConverseStream | Nenhuma — é um turno | DynamoDB com janela e expiração |
| API interna síncrona | API Gateway HTTP ou REST | Lambda | Nenhuma | Sem estado, ou DynamoDB por idempotência |
| Documento chegou | Sem borda: evento do S3 | Lambda | EventBridge + SQS; Step Functions no ramo humano | DynamoDB de rastreio por documento |
| Batch em massa | Sem borda: agendamento | Job de batch do Bedrock | Step Functions coordenando lotes | S3 de entrada e saída |
| Agent autônomo | API Gateway ou fila | AgentCore Runtime ou Fargate | O próprio laço do agent | AgentCore Memory ou DynamoDB |
Repare no que se repete
Lambda aparece em quase todas as linhas, DynamoDB na maioria, e a diferença real está na borda e na orquestração. Isso é bom sinal de arquitetura: o núcleo é estável e o que muda por caso de uso é a periferia. Um time que domina bem esse punhado de serviços cobre praticamente qualquer fluxo de IA corporativa sem precisar de tecnologia nova.
Erros clássicos desta camada
- Tempo de invisibilidade da fila menor que o processamento: a mensagem reaparece enquanto ainda está sendo processada, e você paga a inferência duas vezes.
- Consumidor não idempotente: com entrega ao-menos-uma-vez do outro lado, duplicata em pico é questão de tempo.
- Sem fila de mensagens mortas: um documento problemático vira laço eterno de retry pago.
- Aumentar memória da função para vencer o teto de 15 minutos: o limite é de tempo, não de recurso.
- Máquina de estados granular para item de lote grande: você paga transição de estado onde uma função resolveria.
- Modo de alto volume no ramo que espera humano: a duração limitada não cobre uma revisão que leva dias.
- Publicação em leque sem fila: assinante fora do ar perde a mensagem, e não há como saber quais.
- Carregar a conversa inteira em todo turno: o custo cresce mais que linearmente porque o turno 30 paga os 29 anteriores.
- Tabela de conversas sem expiração: cresce para sempre e guarda dado pessoal além do que a política permite.
- Container provisionado para carga esporádica: capacidade parada custando, quando a função escalaria do zero.
Um agent de investigação passou a ultrapassar 15 minutos de execução. Qual é a primeira alternativa a considerar?
O custo de um assistente de chat cresce desproporcionalmente conforme a conversa avança, mesmo sem aumento de usuários. Qual é a causa mais provável nesta camada?
Próximo passo
Falta a camada que alimenta o modelo: armazenamento, vector stores comparados pelo critério que decide de verdade — quanto custam parados — busca gerenciada e consulta sobre o lago. É onde mora a qualidade da resposta e, no piloto, a maior linha da conta.
Perguntas frequentes
❓ Onde rodar o código que orquestra o agente?
❓ Como coordenar passos de um fluxo de IA?
❓ Onde guardar o estado de uma conversa?
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…