# ADR: LLM Auto-Hospedado (EKS + vLLM) vs API Gerenciada (Bedrock)

Este ADR avalia a decisão entre hospedar modelos de linguagem em infraestrutura própria com EKS e vLLM versus consumir modelos via Amazon Bedrock. A análise cobre custo por token, carga operacional de MLOps, cold start, residência de dados e ponto de break-even por volume de tokens.

- URL: https://fernando.moretes.com/studies/adr-llm-self-hosted-eks-vs-bedrock

- Markdown: https://fernando.moretes.com/studies/adr-llm-self-hosted-eks-vs-bedrock/study.md?lang=pt

- Type: Decisão (ADR)

- Company: Plataforma de IA (cenário)

- Domain: IA / Custo

- Status: accepted

- Date: 2026-02-28

- Tags: llm, bedrock, vllm, eks, gpu, mlops, cost-optimization, ai-platform

- Reading time: 8 min

---

Hospedar seu próprio LLM em GPUs dedicadas parece atraente no papel — controle total, custo marginal baixo em escala, sem vendor lock-in de API. Na prática, você está trocando um problema de fatura por um problema de engenharia. Este ADR documenta a decisão tomada para uma plataforma de IA em crescimento: quando o Bedrock é a escolha certa e em que ponto a operação própria com vLLM no EKS passa a fazer sentido econômico e operacional.

## Ficha Técnica

- **Sistema:** Plataforma de IA — cenário composto baseado em padrões reais de adoção
- **Domínio:** IA Generativa / Otimização de Custos
- **Modelos considerados:** Claude 3 Sonnet/Haiku (Bedrock), Llama 3 70B / Mistral 7B (vLLM self-hosted)
- **Hardware GPU avaliado:** g5.12xlarge (4× A10G, 96 GB VRAM) e p5.48xlarge (8× H100, 640 GB VRAM)
- **Volume de tokens (baseline):** ~500 M tokens/mês na fase inicial; projeção de 5–10 B tokens/mês em 12 meses
- **Requisitos de compliance:** LGPD; dados de PII não podem sair da região AWS sa-east-1
- **Stack de orquestração:** Amazon EKS 1.30, Karpenter, NVIDIA Device Plugin, vLLM 0.5.x, Prometheus + Grafana
- **Status da decisão:** Aceito — Bedrock para fase inicial; migração para vLLM/EKS quando volume superar break-even

## Contexto e Forças em Jogo

A plataforma nasceu como um produto interno de automação de conteúdo e análise de documentos, mas rapidamente ganhou tração como serviço multi-tenant oferecido a clientes corporativos. Em seis meses, o volume de inferência saltou de dezenas de milhares para centenas de milhões de tokens por mês. Nesse ponto, a fatura do Bedrock começou a aparecer de forma relevante no P&L e a pergunta inevitável surgiu: *vale a pena trazer o modelo para dentro de casa?*

A tensão central não é técnica — é econômica e operacional. De um lado, o Bedrock oferece zero overhead de infraestrutura, modelos de ponta (Claude, Titan, Llama via Marketplace), SLA gerenciado, e faturamento por token sem compromisso mínimo no modo on-demand. Do outro, instâncias GPU dedicadas têm custo fixo alto mas custo marginal por token próximo de zero após a amortização — o que inverte a equação de custo em volumes altos.

Há, porém, forças que vão além do custo. A equipe de engenharia conta com dois MLEs experientes, mas nenhum com experiência operacional profunda em clusters GPU em produção. Isso importa: vLLM é uma engine de inferência excelente — suporte a PagedAttention, continuous batching, tensor parallelism — mas exige atenção constante a versões de driver CUDA, compatibilidade de modelo com quantização (AWQ, GPTQ), tuning de parâmetros como `--max-num-seqs`, `--gpu-memory-utilization`, e gestão de OOM em modelos grandes. O custo de aprendizado é real e não aparece em nenhuma planilha de break-even.

Outra força relevante é a heterogeneidade de carga. A plataforma tem picos diurnos pronunciados (razão pico/vale de aproximadamente 8:1) e cargas de batch noturnas. Bedrock absorve picos sem dimensionamento manual; EKS com Karpenter pode fazer scale-out de nós GPU, mas o cold start de um nó g5.12xlarge — incluindo pull de imagem de container com modelo quantizado (~20–40 GB) — pode levar 8–15 minutos, o que é inaceitável para latência interativa.

## Análise de Break-Even por Volume de Tokens

A análise de break-even é o núcleo quantitativo desta decisão. Os números abaixo são estimativas baseadas em preços públicos da AWS (us-east-1, referência 2024) e benchmarks de throughput do vLLM — devem ser recalibrados com preços vigentes e perfil de carga real antes de qualquer decisão de produção.

**Bedrock (Claude 3 Haiku — on-demand):**
- Input: $0,00025 / 1K tokens; Output: $0,00125 / 1K tokens
- Assumindo mix 70% input / 30% output: custo médio ponderado ≈ $0,000550 / 1K tokens
- A 1 B tokens/mês: ~$550/mês
- A 10 B tokens/mês: ~$5.500/mês

**vLLM auto-hospedado (Llama 3 70B em g5.12xlarge):**
- g5.12xlarge on-demand: ~$5,67/hora → ~$4.082/mês (730h)
- Throughput típico com vLLM + PagedAttention + AWQ int4: ~1.500–2.500 tokens/s em carga sustentada (estimativa baseada em benchmarks públicos vLLM)
- A 2.000 tokens/s com utilização de 60%: ~3,7 B tokens/mês por instância
- Custo efetivo: ~$4.082 / 3,7 B ≈ $0,0011 / 1K tokens — ainda mais caro que Haiku
- Com Reserved Instance 1 ano (~40% desconto): ~$2.449/mês → ~$0,00066 / 1K tokens — paridade aproximada
- Com Spot + Reserved mix e utilização >80%: custo pode cair para ~$0,0003–0,0004 / 1K tokens

**Break-even prático (estimativa):**
- Comparando Bedrock Haiku on-demand vs. g5.12xlarge Reserved + alta utilização: break-even em torno de **3–5 B tokens/mês por instância**
- Para modelos maiores (Claude 3 Sonnet vs. Llama 3 70B full precision em p5): o break-even sobe significativamente devido ao custo de hardware
- O break-even real deve incluir: custo de engenharia MLOps (~0,5–1 FTE), licenças de observabilidade, egress de dados, e custo de downtime por incidentes operacionais

**Conclusão quantitativa:** abaixo de ~3 B tokens/mês, Bedrock é economicamente superior mesmo desconsiderando o overhead operacional. Acima de 5–8 B tokens/mês com utilização consistente >70%, o auto-hospedado começa a fazer sentido — mas apenas se a equipe tiver maturidade operacional para sustentar o ambiente.

## Matriz de Decisão: Opções Avaliadas

### Opção A: Amazon Bedrock On-Demand

**Pros**
- Zero overhead de infraestrutura GPU — sem drivers, sem OOM, sem upgrades de CUDA
- Acesso imediato a modelos de ponta (Claude 3.5, Llama 3.1 405B) sem trabalho de fine-tuning de infra
- Faturamento elástico — paga exatamente pelo que usa, ideal para volume imprevisível
- SLA gerenciado pela AWS; sem on-call de infra para equipe de produto
- Dados processados dentro da região AWS (sa-east-1 disponível para alguns modelos)

**Cons**
- Custo por token alto em volumes grandes — economia de escala não se transfere ao cliente
- Sem controle sobre versão exata do modelo — atualizações podem mudar comportamento sem aviso
- Throughput provisionado (Provisioned Throughput) exige compromisso de 1–6 meses sem garantia de utilização
- Modelos open-weight customizados (fine-tuning proprietário) têm suporte limitado

**Verdict:** Escolha correta para fase inicial (<3 B tokens/mês) e para equipes sem maturidade MLOps GPU

### Opção B: EKS + vLLM em GPUs Dedicadas (g5/p5)

**Pros**
- Custo marginal por token muito baixo em alta utilização — break-even favorável acima de 5 B tokens/mês
- Controle total sobre versão de modelo, quantização, configuração de contexto e fine-tuning
- vLLM oferece continuous batching e PagedAttention — throughput superior a soluções naive
- Dados nunca saem do VPC — compliance máximo para PII e dados sensíveis
- Possibilidade de usar Spot Instances para workloads batch com economia adicional de 60–70%

**Cons**
- Alto custo fixo independente de utilização — instância GPU parada ainda custa ~$4K/mês
- Cold start de nó GPU: 8–15 minutos para novo nó Karpenter com imagem de modelo grande
- Carga operacional significativa: upgrades de driver, compatibilidade CUDA/PyTorch/vLLM, OOM tuning
- Atualização de modelo requer novo rollout de deployment — não é transparente como Bedrock
- Requer expertise MLOps dedicada — custo oculto de ~0,5–1 FTE para operação estável

**Verdict:** Justificado acima de 5–8 B tokens/mês com equipe MLOps madura e carga previsível

### Opção C: Híbrido — Bedrock + vLLM por Tipo de Carga

**Pros**
- Bedrock para picos interativos e modelos frontier; vLLM para batch previsível e modelos open-weight
- Otimiza custo por segmento de carga sem comprometer latência interativa
- Permite construir maturidade operacional GPU gradualmente sem risco de produção total

**Cons**
- Complexidade de roteamento — requer camada de abstração (LLM gateway) para direcionar requests
- Dois stacks para operar, monitorar e manter — overhead dobrado de observabilidade
- Consistência de comportamento entre modelos diferentes pode ser difícil de garantir

**Verdict:** Caminho evolutivo recomendado para plataformas em crescimento acima de 2 B tokens/mês

## Decisão

**Status:** accepted

**Contexto**

A plataforma está em fase de crescimento com ~500 M tokens/mês, equipe de 2 MLEs sem experiência operacional GPU em produção, requisito de residência de dados LGPD em sa-east-1, e projeção de 5–10 B tokens/mês em 12 meses. O custo atual do Bedrock é gerenciável mas a trajetória de crescimento tornará a fatura significativa. A equipe precisa de tempo para construir maturidade operacional antes de assumir a responsabilidade de um cluster GPU em produção.

**Decisão**

Adotar Amazon Bedrock como camada primária de inferência para a fase atual (0–3 B tokens/mês), com Provisioned Throughput para cargas base previsíveis e on-demand para picos. Em paralelo, construir e validar o stack EKS + vLLM em ambiente de staging com carga real de batch. Migrar workloads batch para vLLM/EKS quando: (a) volume de batch superar 2 B tokens/mês de forma consistente, (b) a equipe completar 90 dias de operação do cluster em staging sem incidentes críticos, e (c) o custo projetado do Bedrock superar o custo total de propriedade do EKS (incluindo FTE MLOps) por margem >30%. Manter Bedrock como fallback e para modelos frontier sem equivalente open-weight.

**Consequências**
- POSITIVO: Risco operacional zero na fase inicial — equipe foca em produto, não em infra GPU
- POSITIVO: Caminho claro e mensurável para migração com critérios objetivos de trigger
- POSITIVO: Provisioned Throughput reduz custo em ~30–40% para carga base previsível vs on-demand
- NEGATIVO: Custo por token mais alto que o necessário se volume crescer mais rápido que o previsto
- NEGATIVO: Dependência de modelos e versões controlados pela AWS/Anthropic — risco de breaking changes
- NEGATIVO: Requer LLM gateway desde o início para abstrair provedor e facilitar migração futura

## Carga Operacional de MLOps: O Custo que Não Aparece na Planilha

Toda análise de break-even que vi em discussões de equipe sobre self-hosting de LLM comete o mesmo erro: compara custo de instância com custo de API e para por aí. Isso subestima sistematicamente o custo real de operar GPUs em produção.

Vamos ser concretos sobre o que significa manter vLLM em EKS em produção. Primeiro, a cadeia de compatibilidade: vLLM tem dependências estritas entre versão de CUDA, versão de PyTorch, e versão do driver NVIDIA no host. Um upgrade de AMI do nó EKS pode quebrar silenciosamente a inferência se o driver não for compatível com a versão de CUDA compilada no container. Isso não é hipotético — é um padrão recorrente em projetos que acompanhei. O NVIDIA Device Plugin para Kubernetes adiciona outra camada de configuração que precisa ser gerenciada.

Segundo, o tuning de vLLM não é trivial. Os parâmetros `--gpu-memory-utilization` (tipicamente 0.85–0.90), `--max-num-seqs` (número máximo de sequências em flight), `--max-model-len` (tamanho máximo de contexto), e a escolha de quantização (AWQ vs. GPTQ vs. FP8) afetam diretamente throughput, latência P99 e risco de OOM. Um modelo Llama 3 70B em FP16 requer ~140 GB de VRAM — não cabe em um único g5.12xlarge (96 GB). Com AWQ int4, cai para ~35–40 GB e cabe com folga, mas a qualidade de geração pode degradar em tarefas específicas. Essa decisão precisa ser validada empiricamente para cada caso de uso.

Terceiro, a gestão de cold start é um problema de produto, não apenas de infra. Karpenter pode provisionar um novo nó GPU em resposta a um pod pendente, mas o tempo total — provisioning EC2 + bootstrap do nó + pull da imagem de container + carregamento do modelo em VRAM — é da ordem de 8–15 minutos para modelos grandes. Para workloads interativos, isso é inaceitável. A solução é manter um número mínimo de nós quentes (aumentando custo fixo) ou usar node image caching (EKS Bottlerocket + snapshot de EBS com imagem pré-pulled). Ambas as abordagens têm custo e complexidade adicionais.

Quarto, observabilidade. Bedrock expõe métricas via CloudWatch sem configuração. Com vLLM, você precisa instrumentar o endpoint `/metrics` do Prometheus, configurar dashboards de GPU utilization (DCGM Exporter), alertas de VRAM, throughput de tokens/s, e latência por percentil. Não é difícil, mas é trabalho que precisa ser feito e mantido.

A conclusão é que o custo operacional real de um cluster vLLM em produção — quando você inclui tempo de engenharia, incidentes, upgrades, e observabilidade — é equivalente a 0,5–1 FTE de engenheiro sênior. Para uma equipe pequena, isso pode ser mais caro que a diferença de custo de API que você está tentando economizar.

## Comparativo de Custo Estimado por Volume de Tokens
| Critério | Volume Mensal | Bedrock Haiku On-Demand | Bedrock Provisioned Throughput | vLLM g5.12xl On-Demand | vLLM g5.12xl Reserved 1y |
| --- | --- | --- | --- | --- | --- |
| 500 M tokens | ~$275/mês | ~$180/mês (est.) | ~$4.082/mês | ~$2.449/mês | Bedrock |
| 2 B tokens | ~$1.100/mês | ~$720/mês (est.) | ~$4.082/mês | ~$2.449/mês | Bedrock PT |
| 5 B tokens | ~$2.750/mês | ~$1.800/mês (est.) | ~$4.082/mês (1 inst.) | ~$2.449/mês (1 inst.) | Híbrido / Avaliar |
| 10 B tokens | ~$5.500/mês | ~$3.600/mês (est.) | ~$8.164/mês (2 inst.) | ~$4.898/mês (2 inst.) | vLLM Reserved + FTE |

## Arquitetura Alvo: Plataforma de IA com Roteamento Híbrido

Diagrama da arquitetura alvo após decisão aceita: LLM Gateway central roteando entre Bedrock (cargas interativas e frontier models) e vLLM/EKS (batch e modelos open-weight em alta utilização). Inclui camada de observabilidade, controle de acesso e residência de dados.

### 👤 Clients

- Web App / API Clients (user)
- Batch Job Orchestrator (compute)

### 🔐 Security & Gateway

- API Gateway + WAF (security)
- LLM Gateway (LiteLLM / custom) (edge)
- Routing Logic model / load / cost (compute)

### ☁️ Bedrock (Managed)

- Bedrock On-Demand (ai)
- Bedrock Provisioned Throughput (ai)
- Claude 3 Sonnet / Haiku (ai)

### 🖥️ EKS + vLLM (Self-Hosted)

- EKS Service (vLLM endpoint) (compute)
- vLLM Pod Llama 3 70B AWQ (ai)
- Karpenter Node Provisioner (compute)
- g5.12xlarge 4× A10G GPU (compute)
- EBS Snapshot Model Image Cache (storage)

### 📊 Observability

- Prometheus + DCGM Exporter (data)
- Grafana GPU / Token Dashboards (frontend)
- CloudWatch Bedrock Metrics (data)

### 🗄️ Data & State

- ElastiCache Prompt Cache (Redis) (data)
- S3 Inference Logs (storage)

### Fluxos

- webapp -> apigw: HTTPS
- batchjob -> apigw: batch requests
- apigw -> llmgw: authn/authz
- llmgw -> cache: cache lookup
- llmgw -> router: route decision
- router -> bedrock_od: picos / frontier
- router -> bedrock_pt: carga base
- router -> eks_svc: batch / open-weight
- bedrock_od -> claude: API call
- bedrock_pt -> claude: provisioned
- eks_svc -> vllm_pod: k8s service
- vllm_pod -> gpu_node: CUDA / VRAM
- karpenter -> gpu_node: provision
- gpu_node -> ebs_snap: image cache
- vllm_pod -> prometheus: /metrics
- prometheus -> grafana
- bedrock_od -> cloudwatch: metrics
- llmgw -> s3_logs: audit log

## Avaliação Well-Architected

- **security**: Bedrock processa dados dentro da AWS sem exposição à internet pública; VPC Endpoint recomendado para eliminar egress. vLLM no EKS deve operar em namespace isolado com Network Policy restritiva e IRSA para acesso a S3/secrets. Logs de inferência em S3 com SSE-KMS para auditoria LGPD. LLM Gateway é o ponto central de authn/authz — deve validar JWT e aplicar rate limiting por tenant.
- **reliability**: Bedrock tem SLA gerenciado; o risco de confiabilidade está no LLM Gateway (SPOF potencial — deve ser multi-AZ com ALB). Para vLLM/EKS, o risco principal é OOM em picos de contexto longo — mitigado com `--max-model-len` conservador e HPA baseado em tokens/s. Fallback automático do gateway para Bedrock em caso de falha do endpoint vLLM é essencial.
- **performance**: vLLM com PagedAttention e continuous batching oferece throughput superior para batch; Bedrock é superior para latência P50 interativa sem warm-up. Cache de prompts no Redis (ElastiCache) pode reduzir 20–40% das chamadas para prompts repetitivos (system prompts fixos, templates). Tensor parallelism no vLLM para modelos >70B requer múltiplas GPUs com NVLink — considerar p4d/p5 para esses casos.
- **cost**: Break-even entre Bedrock e vLLM/EKS está em 3–5 B tokens/mês para Haiku-equivalente com utilização >70%. Provisioned Throughput do Bedrock reduz custo ~30–40% para carga base previsível. Spot Instances para pods vLLM de batch podem reduzir custo GPU em 60–70% com checkpoint de estado adequado. Custo oculto de MLOps (0,5–1 FTE) deve ser incluído no TCO.
- **sustainability**: GPUs dedicadas ociosas têm pegada de carbono fixa independente de utilização — utilização >70% é imperativa tanto para custo quanto para sustentabilidade. Bedrock, por ser multi-tenant, tem melhor eficiência energética por token em volumes baixos. Regiões com energia renovável (us-west-2) devem ser consideradas para workloads batch sem requisito de residência de dados.

> **Minha Perspectiva Senior:** Já vi essa discussão acontecer dezenas de vezes em empresas de diferentes tamanhos, e o padrão de erro é sempre o mesmo: a equipe técnica faz uma planilha de custo de instância vs. custo de API, o número favorece o self-hosting em volumes projetados, e a decisão é tomada sem considerar o denominador oculto — o custo de operar GPUs em produção com a qualidade que um produto real exige.

Minha posição é clara: **a menos que você já tenha um time com experiência operacional comprovada em clusters GPU, comece com Bedrock e invista o tempo economizado em construir o LLM Gateway corretamente**. O Gateway é o ativo mais valioso dessa arquitetura — ele abstrai o provedor, permite migração gradual, centraliza observabilidade e controle de custo, e é o que vai permitir que você mova cargas para vLLM quando o momento certo chegar sem reescrever a aplicação.

Um erro específico que vejo frequentemente: equipes que escolhem self-hosting cedo demais e dimensionam para o pico de demanda projetado. Resultado: GPUs rodando a 20–30% de utilização, custo real por token 3–4× maior que o Bedrock que estavam tentando evitar, e dois engenheiros sênior gastando 30% do tempo em manutenção de infra em vez de produto.

O outro lado também existe: vi equipes que ficaram no Bedrock por inércia muito além do break-even, pagando 5–10× mais que o necessário. A disciplina de revisar a decisão com critérios objetivos — como os que defini neste ADR — é o que evita ambos os erros.

Sobre compliance e LGPD: Bedrock em sa-east-1 resolve a residência de dados para a maioria dos casos. Se o requisito for que **nenhum dado de PII saia do VPC** (não apenas da região), então vLLM/EKS é mandatório independente de volume — e esse critério deve estar explícito no ADR, não implícito.

## Veredicto

A decisão correta entre Bedrock e vLLM/EKS não é técnica — é uma função de volume de tokens, maturidade operacional da equipe, e perfil de carga. Para volumes abaixo de 3 B tokens/mês ou equipes sem experiência GPU em produção, Bedrock é economicamente e operacionalmente superior sem contestação. O break-even real com vLLM/EKS — incluindo custo de FTE MLOps — está na faixa de 5–8 B tokens/mês com utilização consistente acima de 70%, e não deve ser calculado sem esses custos ocultos.

A arquitetura recomendada não é uma escolha binária: é um LLM Gateway como camada de abstração obrigatória desde o dia zero, Bedrock como camada primária na fase inicial, e vLLM/EKS construído e validado em paralelo em staging. A migração acontece quando critérios objetivos e mensuráveis são atingidos — não quando alguém acha que 'já está na hora'.

O investimento mais importante desta decisão não está na escolha de GPU ou de API: está na qualidade do LLM Gateway. Um gateway bem construído — com roteamento por modelo, rate limiting por tenant, cache de prompts, logging de inferência, e fallback automático — é o que transforma uma decisão de infraestrutura em uma vantagem competitiva de produto. Sem ele, você está apenas trocando um vendor lock-in por outro.

## Referências

- [Amazon Bedrock — Pricing](https://aws.amazon.com/bedrock/pricing/)
- [vLLM — Documentation](https://docs.vllm.ai/)
- [Amazon EKS — User Guide](https://docs.aws.amazon.com/eks/latest/userguide/)

## Fontes do caso

- [Amazon Bedrock — Pricing](https://aws.amazon.com/bedrock/pricing/)
- [vLLM — Documentation](https://docs.vllm.ai/)
- [Amazon EKS — User Guide](https://docs.aws.amazon.com/eks/latest/userguide/)
