# Playbook: Vector Store na AWS — OpenSearch Serverless vs Aurora pgvector vs S3 Vectors

Escolher o vector store errado é onde a conta de RAG explode — ou onde a latência entrega p99 inaceitável em produção. Este playbook mapeia os três caminhos principais na AWS (OpenSearch Serverless, Aurora pgvector, S3 Vectors) por três eixos reais: latência exigida, modelo de custo e carga operacional. Saia com uma decisão defensável, não com a escolha do tutorial.

- URL: https://fernando.moretes.com/studies/playbook-vector-store-na-aws-opensearch-pgvector-s3-vectors

- Markdown: https://fernando.moretes.com/studies/playbook-vector-store-na-aws-opensearch-pgvector-s3-vectors/study.md?lang=pt

- Type: Playbook

- Domain: AWS / RAG

- Date: 2025-07-25

- Tags: vector-store, RAG, OpenSearch, pgvector, S3-Vectors, AWS, GenAI, architecture

- Reading time: 8 min

---

Todo tutorial de RAG aponta para um vector store. Nenhum tutorial te diz o que acontece quando o tráfego some às 3h da manhã e você ainda está pagando por OCUs ociosas, ou quando seu índice HNSW cresce sem tuning e a latência dobra silenciosamente. A escolha do vector store é uma decisão de custo, latência e operação — não de feature list. Este playbook te dá os três eixos de decisão e um caminho claro para cada perfil de carga.

## O que você vai conseguir decidir depois deste playbook

- Qual vector store escolher dado seu p99 de latência exigido, volume de vetores e perfil de acesso (quente vs arquivo)
- Quando o custo ocioso do OpenSearch Serverless justifica — e quando ele te mata
- Se você já tem Aurora PostgreSQL, se vale ou não migrar para um store dedicado
- O perfil exato de carga para o qual S3 Vectors foi construído (e o que ele não é)
- Os três anti-padrões que aparecem em produção e como evitá-los antes do deploy

## Referência rápida — os três stores em números

- **OpenSearch Serverless — custo mínimo (OCU):** 0.24 USD/OCU-hora; mínimo 2 OCUs de indexação + 2 de busca = ~$345/mês em repouso (us-east-1, estimativa)
- **Aurora pgvector — dimensões suportadas:** Até 16.000 dimensões por vetor (pgvector ≥ 0.7); índices HNSW e IVFFlat disponíveis
- **S3 Vectors — modelo de preço:** Cobrado por GB armazenado + por requisição de query; sem custo de compute ocioso (GA 2025)
- **Integração nativa com Bedrock Knowledge Bases:** OpenSearch Serverless: sim (nativa). Aurora pgvector: sim (via RDS Data API). S3 Vectors: sim (GA 2025)
- **Busca híbrida (vetorial + lexical):** OpenSearch Serverless: sim (BM25 + kNN nativo). Aurora pgvector: manual (pg_trgm + pgvector). S3 Vectors: não nativo
- **Modelo operacional:** OpenSearch Serverless: totalmente gerenciado. Aurora pgvector: gerenciado (RDS), mas tuning de índice é seu. S3 Vectors: totalmente gerenciado

## O modelo mental que desbloqueia a decisão

Pense em vector stores como você pensa em bancos de dados: **não existe o melhor — existe o certo para o perfil de acesso**. O erro clássico é tratar a escolha como uma decisão de features ("qual suporta mais dimensões?") quando na prática ela é uma decisão de três eixos ortogonais:

**Eixo 1 — Latência exigida (p99):** Qual é o SLA da sua aplicação? Um chatbot interativo tolera ~200ms de p99 na busca vetorial. Um pipeline batch de reranking pode tolerar segundos. Um agente autônomo que faz múltiplas buscas por turno precisa de latência consistente, não apenas mediana baixa. O p99 é o número que importa, não o p50.

**Eixo 2 — Modelo de custo (ocioso vs volume):** OpenSearch Serverless cobra por OCU-hora independente de carga — você paga pelo piso, não pelo uso. Aurora pgvector cobra pela instância RDS (que você provavelmente já tem). S3 Vectors cobra por storage e por query — custo quase zero em repouso, cresce com volume de queries. Se sua carga é altamente variável ou sazonal, o modelo de custo domina a decisão.

**Eixo 3 — Carga operacional (gerenciado vs você tuna):** OpenSearch Serverless abstrai sharding, replicação e scaling. S3 Vectors é objeto + query, sem infraestrutura visível. Aurora pgvector te dá controle total — e responsabilidade total: você precisa escolher entre HNSW e IVFFlat, definir `m` e `ef_construction`, monitorar bloat de índice, e entender que um `VACUUM` mal-timed pode degradar latência em produção.

A maioria dos erros de arquitetura que vejo vem de ignorar o Eixo 2 (custo ocioso) ou o Eixo 3 (tuning de índice). O tutorial usa OpenSearch Serverless porque é o caminho de menor fricção para um demo. Produção é diferente.

## Comparação direta — os três vector stores na AWS
| Critério | Critério | OpenSearch Serverless | Aurora pgvector | S3 Vectors |
| --- | --- | --- | --- | --- |
| Melhor para | — | RAG agêntico, busca híbrida, filtros ricos, carga variável com SLA de ms | Você já tem Postgres; vetores junto dos relacionais; joins com metadados de negócio | Corpus enorme (bilhões de vetores), acesso esporádico, custo de storage dominante |
| Latência p99 típica (busca ANN) | — | 10–80ms (carga aquecida, OCUs adequados) | 5–150ms (depende de índice, instância e vacuum) | 50–500ms+ (perfil arquivo; cold start possível) |
| Modelo de custo | — | OCU-hora (mínimo ~$345/mês ocioso); escala automática para cima | Instância RDS + storage; você já paga se o banco existe | GB armazenado + por query; custo ocioso quase zero |
| Busca híbrida (vetorial + lexical) | — | Nativa (BM25 + kNN, normalization pipeline) | Manual (pg_trgm + pgvector; você escreve o SQL) | Não disponível nativamente |
| Filtros de metadados | — | Ricos (pre-filter e post-filter, nested fields) | Completos via SQL (WHERE clause nativa) | Suportados por bucket/prefix; filtros avançados limitados |
| Carga operacional | — | Baixa (totalmente gerenciado; sem tuning de índice exposto) | Média-alta (tuning HNSW/IVFFlat, vacuum, bloat, instância sizing) | Baixa (totalmente gerenciado; modelo objeto + query) |
| Integração Bedrock Knowledge Bases | — | Nativa e madura (opção padrão nos tutoriais) | Sim (via RDS Data API) | Sim (GA 2025) |
| Quando NÃO usar | — | Carga baixa/esporádica onde o custo mínimo não se justifica; orçamento restrito em dev/staging | Sem Postgres existente; equipe sem experiência em tuning de índice; volume > 100M vetores sem sharding | SLA de ms em produção interativa; busca híbrida necessária; filtros complexos por metadados |

## OpenSearch Serverless: o poder e a armadilha do piso de custo

O OpenSearch Serverless com vector engine é genuinamente o store mais capaz para RAG de produção com requisitos complexos. Busca híbrida nativa (BM25 + kNN com normalization pipeline), filtros pre e post, integração direta com Bedrock Knowledge Bases, e scaling automático de OCUs são diferenciais reais — não marketing.

O problema é o modelo de custo. Cada collection de vector search requer no mínimo 2 OCUs de indexação e 2 OCUs de busca. A 0.24 USD/OCU-hora, isso é aproximadamente **$345/mês em repouso**, sem uma única query. Em desenvolvimento, staging, ou aplicações com carga baixa e variável, esse piso é inaceitável. Vi equipes mantendo três ambientes (dev, staging, prod) com OpenSearch Serverless e pagando ~$1.000/mês antes de processar um único vetor real.

O scaling automático é real, mas assimétrico: sobe rápido quando a carga aumenta, desce devagar. Picos de carga podem provisionar OCUs adicionais que demoram horas para escalar de volta. Monitore `SearchOCUs` e `IndexingOCUs` no CloudWatch e configure alertas de billing antes de ir para produção.

Para o perfil certo — RAG agêntico com múltiplas buscas por turno, busca híbrida, filtros ricos, carga razoavelmente constante acima do piso — é a escolha correta e o custo se justifica. Para todo o resto, avalie os outros dois caminhos primeiro.

## Aurora pgvector: o poder do Postgres — e o tuning que ninguém faz

Se você já opera Aurora PostgreSQL, adicionar pgvector é a decisão de menor fricção possível: uma extensão, um tipo de coluna, um índice. Você mantém transações ACID, joins com dados relacionais, controle de acesso por row-level security, e toda a toolchain que sua equipe já conhece. Para casos onde os vetores precisam estar junto dos metadados relacionais — documentos com versão, permissões por usuário, joins com tabelas de negócio — essa co-localização elimina uma classe inteira de problemas de consistência.

O que a maioria das equipes ignora é o tuning de índice. pgvector suporta dois tipos:

- **IVFFlat**: divide o espaço vetorial em listas (`lists`), busca nas mais próximas (`probes`). Mais rápido para construir, menos preciso. Exige que o índice seja construído *após* os dados estarem carregados (senão as listas ficam desbalanceadas). Parâmetro crítico: `ivfflat.probes` — aumentar melhora recall mas piora latência.

- **HNSW**: grafo hierárquico navegável. Melhor recall e latência, mas consome mais memória e demora mais para construir. Parâmetros críticos: `m` (conexões por nó, padrão 16) e `ef_construction` (tamanho da fila de candidatos durante build, padrão 64). Para produção com SLA de ms, HNSW é a escolha certa — mas você precisa dimensionar `shared_buffers` e `work_mem` para que o índice caiba em memória.

O problema silencioso é o **index bloat**: inserções e updates frequentes fragmentam o índice HNSW. Um `REINDEX CONCURRENTLY` periódico é necessário em cargas de escrita contínua. E um `AUTOVACUUM` mal-configurado pode bloquear queries de busca em momentos críticos.

Regra prática: se você não tem alguém na equipe que sabe o que é `ef_search` e quando ajustá-lo, pense duas vezes antes de escolher pgvector para um SLA de p99 < 100ms em produção.

## Matriz de decisão — qual vector store para seu caso

### OpenSearch Serverless (Vector Engine)

**Pros**
- Busca híbrida nativa (BM25 + kNN) sem código extra
- Filtros ricos de metadados (pre/post-filter) nativos
- Scaling automático de OCUs; sem tuning de índice exposto
- Integração nativa e madura com Bedrock Knowledge Bases
- Ideal para RAG agêntico com múltiplas buscas por turno

**Cons**
- Custo mínimo ~$345/mês mesmo sem queries (2+2 OCUs)
- Scale-down assimétrico: sobe rápido, desce devagar
- Sem acesso a índice subjacente; debugging de recall limitado
- Custo proibitivo para dev/staging se não compartilhado

**Verdict:** USE quando: RAG de produção com busca híbrida, filtros complexos, carga constante acima do piso de custo. NÃO USE quando: carga esporádica, orçamento restrito, ou você só precisa de similaridade simples.

### Aurora PostgreSQL + pgvector

**Pros**
- Custo zero adicional se Aurora já existe no stack
- Joins nativos com dados relacionais (metadados, permissões, versões)
- ACID, row-level security, toolchain Postgres familiar
- Controle total do índice (HNSW vs IVFFlat, parâmetros)
- Suporta até 16.000 dimensões (pgvector ≥ 0.7)

**Cons**
- Tuning de índice é responsabilidade sua (HNSW params, vacuum, bloat)
- Sem busca híbrida nativa; pg_trgm é workaround, não solução
- Escalabilidade vetorial limitada pela instância RDS (sem sharding automático)
- Index bloat em cargas de escrita contínua requer manutenção ativa

**Verdict:** USE quando: Aurora já existe, vetores precisam de joins relacionais, equipe tem experiência em Postgres tuning. NÃO USE quando: você precisa de busca híbrida de verdade, volume > 50-100M vetores, ou a equipe não tem expertise em índices.

### S3 Vectors

**Pros**
- Custo ocioso quase zero (paga por GB + por query, não por compute)
- Escala para bilhões de vetores sem gestão de infraestrutura
- Totalmente gerenciado; modelo simples de objeto + query
- Integração com Bedrock Knowledge Bases (GA 2025)
- Ideal para pipelines batch, corpora de arquivo, embeddings históricos

**Cons**
- Latência p99 mais alta; não adequado para SLA de ms em produção interativa
- Sem busca híbrida nativa
- Filtros avançados de metadados limitados comparado ao OpenSearch
- Produto mais novo (GA 2025); ecossistema de tooling ainda amadurecendo

**Verdict:** USE quando: volume enorme, acesso esporádico, custo de storage é o driver, pipeline batch ou RAG offline. NÃO USE quando: latência de ms é requisito, busca híbrida é necessária, ou a aplicação é interativa em tempo real.

## Como decidir: 5 perguntas em ordem

1. **Passo 1: Qual é o seu p99 de latência exigido?** — Se p99 < 200ms em produção interativa → elimine S3 Vectors. Se p99 pode ser segundos (batch, pipeline offline) → S3 Vectors é candidato forte. Teste: defina o SLA antes de escolher o store, não depois.

2. **Passo 2: Você já tem Aurora PostgreSQL em produção?** — Se sim → avalie pgvector primeiro. Calcule o custo da instância existente vs o custo mínimo de OpenSearch Serverless. Se os vetores precisam de joins com dados relacionais → pgvector é fortemente favorecido. Se não tem Postgres → pgvector não é o caminho de menor fricção.

3. **Passo 3: Você precisa de busca híbrida (vetorial + lexical)?** — Se sim → OpenSearch Serverless é o único dos três com suporte nativo real. pgvector + pg_trgm funciona mas é um workaround que você vai manter. S3 Vectors não suporta. Valide: teste recall com queries reais antes de assumir que busca vetorial pura é suficiente.

4. **Passo 4: Qual é o perfil de carga (constante vs esporádica)?** — Calcule: (horas/mês com carga real) × (OCU-hora OpenSearch) vs custo mínimo mensal. Se a carga é < 50% do tempo → o custo ocioso do OpenSearch Serverless provavelmente não se justifica. Carga altamente sazonal → S3 Vectors ou pgvector (se já existe) são mais eficientes em custo.

5. **Passo 5: Sua equipe tem capacidade de tuning de índice?** — Se escolher pgvector: defina quem é responsável por HNSW params, vacuum schedule, e monitoramento de bloat antes do deploy. Se ninguém na equipe sabe o que é `ef_construction` → ou invista em capacitação ou escolha OpenSearch Serverless. Não há meio-termo: índice mal-tuned em pgvector em produção é uma bomba-relógio de latência.

## Árvore de decisão — vector store na AWS

Fluxo de decisão pelos três eixos: latência p99, existência de Postgres, e perfil de carga/custo. Cada nó de decisão leva a um store recomendado ou a uma qualificação adicional.

### 🎯 Entrada

- Preciso de um vector store para RAG na AWS (user)

### ⏱️ Eixo 1: Latência

- p99 < 200ms em produção interativa? (compute)
- S3 Vectors ✓ Batch / Arquivo ✓ Custo mínimo ✓ Bilhões de vetores (storage)

### 🗄️ Eixo 2: Postgres existente

- Aurora PostgreSQL já existe no stack? (compute)
- Aurora pgvector ✓ Joins relacionais ✓ Custo zero adicional ⚠️ Tuning necessário (data)

### 🔍 Eixo 3: Busca híbrida + Custo

- Busca híbrida ou filtros ricos? (compute)
- Carga constante > 50% do tempo ou SLA crítico? (compute)

### ✅ Recomendações

- OpenSearch Serverless ✓ Híbrido nativo ✓ Filtros ricos ✓ RAG agêntico ⚠️ ~$345/mês mínimo (ai)
- Aurora pgvector ✓ Já tem Postgres ✓ Custo eficiente ⚠️ Tuning obrigatório (data)
- OpenSearch Serverless (carga justifica custo) (ai)
- S3 Vectors (custo ocioso inaceitável) (storage)

### Fluxos

- start -> lat_q
- lat_q -> s3v: NÃO (batch/arquivo)
- lat_q -> pg_q: SIM (ms exigido)
- pg_q -> pgv: SIM + joins relacionais
- pg_q -> hyb_q: NÃO / sem joins
- hyb_q -> oss: SIM (híbrida/filtros)
- hyb_q -> cost_q: NÃO (similaridade simples)
- cost_q -> oss2: SIM (carga constante)
- cost_q -> s3v2: NÃO (esporádica)

> **Anti-padrões que aparecem em produção:** **1. Escolher pelo tutorial, não pelo perfil de carga.** OpenSearch Serverless é o padrão em todos os exemplos de Bedrock Knowledge Bases. Isso não significa que é a escolha certa para você. Se sua carga é esporádica ou você está em dev/staging, o custo mínimo vai aparecer na sua fatura todos os meses sem entregar valor proporcional.

**2. Ignorar o custo ocioso do OpenSearch Serverless.** O scaling automático sobe rápido e desce devagar. Um pico de carga às 14h pode manter OCUs provisionadas até as 17h. Sem alertas de billing e sem monitoramento de `SearchOCUs`, você descobre o problema no final do mês. Configure `aws cloudwatch put-metric-alarm` para OCU count antes do go-live.

**3. Deployar pgvector sem tuning de índice.** O comportamento padrão do pgvector sem índice é exact search (sequential scan) — funciona perfeitamente em desenvolvimento com 10.000 vetores, explode em produção com 10 milhões. Sem `CREATE INDEX USING hnsw` explícito e sem configurar `ef_search` no runtime, você vai ter latência de segundos onde esperava milissegundos. E o pior: vai funcionar nos testes e falhar só sob carga real.

> **Regra de bolso:** **Se você está pagando pelo compute, exija o p99. Se você está pagando pelo storage, aceite a latência.**

OpenSearch Serverless cobra por compute (OCU-hora) — exija latência de ms em troca. S3 Vectors cobra por storage e query — aceite latência mais alta como trade-off do custo. Aurora pgvector cobra pela instância que você já tem — o custo incremental é baixo, mas o custo operacional (tuning) é alto. Mapeie o que você está pagando e o que está recebendo em troca.

> **Minha perspectiva — o que eu faço na prática:** Na maioria dos projetos que arquiteto, a decisão de vector store é determinada antes de qualquer benchmark: eu olho para o stack existente primeiro. Se há Aurora PostgreSQL com carga razoável, começo com pgvector — a extensão está disponível, o custo incremental é quase zero, e o time já sabe operar Postgres. Eu documento os parâmetros HNSW escolhidos, crio um runbook de manutenção de índice, e monitoro `pg_stat_user_indexes` para bloat. Isso resolve 60% dos casos.

Para os outros 40% — quando não há Postgres, quando busca híbrida é requisito real (não aspiracional), ou quando o RAG é agêntico com múltiplas buscas por turno — eu uso OpenSearch Serverless. Mas nunca sem antes calcular o custo mínimo mensal e apresentar isso ao cliente/stakeholder como custo fixo de infraestrutura, não como custo variável.

S3 Vectors eu reservo para pipelines de embedding em escala (ingestão de corpus histórico, embeddings de documentos legados) onde o acesso é esporádico e o volume é grande. É um produto novo e eu ainda não o colocaria como store primário de um RAG interativo de produção sem benchmarks extensivos de latência no caso específico.

O que eu nunca faço: escolher o store pelo tutorial sem passar pelos cinco passos de decisão. A conta de RAG explode exatamente aí.

## Veredito

Não existe vector store certo — existe o certo para o seu perfil. OpenSearch Serverless é o mais capaz para RAG complexo, mas você paga o piso todo mês independente de uso. Aurora pgvector é a escolha mais eficiente em custo se Postgres já existe, mas o tuning de índice é seu problema. S3 Vectors é a escolha certa para volume e custo de repouso, mas não para p99 de ms. Decida pelos três eixos — latência, custo, operação — não pela lista de features do tutorial. A conta de RAG explode quando você escolhe pelo caminho de menor fricção no demo e descobre o modelo de custo real em produção.

## Referências

- [Amazon OpenSearch Serverless — Vector engine documentation](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/serverless-vector-search.html)
- [Amazon Aurora PostgreSQL — pgvector documentation](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.VectorDB.html)
- [Amazon S3 Vectors — User Guide](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-vectors.html)
- [AWS Blog — Choosing a vector store for RAG](https://aws.amazon.com/blogs/database/)

## Fontes do caso

- [Amazon OpenSearch Serverless — Vector engine](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/serverless-vector-search.html)
- [Amazon Aurora PostgreSQL — pgvector](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.VectorDB.html)
- [Amazon S3 Vectors](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-vectors.html)
- [AWS — Choosing a vector store for RAG](https://aws.amazon.com/blogs/database/)
