“Findability is a feature, not um detalhe.” — #30DiasJava DX Charter
🎯 Objetivo do Day 8
O Day 8/30 foi sobre discoverability. O desafio: entregar um Search Service que combina busca textual com similaridade semântica, servindo desde landing pages até a assistente do projeto.
🛠️ Destaques da implementação
- Pipeline híbrido: PostgreSQL com
pg_trgmpara ranking textual +pgvectorpara semântica. - Indexação incremental: eventos
ContentIndexedEventalimentam o workersearch-indexer, que normaliza conteúdo, gera embeddings e mantémsearch_index_audit. - API flexível: endpoint
/api/searchaceita filtros por tipo, liga/desliga busca semântica e devolve relevância combinada (rank textual + similaridade). - Quotas e segurança: JWT para consumidores internos,
X-API-Keyrotacionável para integrações, rate limiting em Redis e auditoria anonimizada. - Observabilidade: métricas (
search_latency_seconds,search_semantic_usage_total,search_index_backlog), logs comtraceId/queryHashe traces do pipeline completo.
💡 Lições do dia
- Embeddings só entregam valor quando convivem com filtros estruturados — não adianta listas irrelevantes.
- Versão de schema é fundamental: cada documento indexado traz
schemaVersionpara evitar incompatibilidades. - Backpressure importa: medir backlog de indexação evita que novos conteúdos fiquem invisíveis.
🔗 Recursos
- Artigo completo: https://enouveau.io/blog/2025/11/08/search-service-vector-ops.html
- Repositório: https://github.com/adelmonsouza/30DiasJava-Day08-Observability
- Projeto pessoal: Este é um projeto do desafio #30DiasJava, mantido independentemente para fins educacionais.
Next episode → Day 9/30 — Payment Service, Ledgers, and Idempotent Webhooks