A equipe de engenharia por trás de um serviço de hospedagem de vídeos substituiu seu índice SQLite FTS5 por um cluster OpenSearch, reduzindo as consultas sem resultados de 12% para 1,4% e aumentando a taxa de busca para clique em 9%, mantendo a latência abaixo de 28 ms.

Por que a mudança tornou-se urgente

A extensão de busca de texto completo do SQLite (FTS5) é atraente: ela reside no mesmo arquivo que o restante dos dados, não possui custos de licenciamento e retorna correspondências instantaneamente para correspondências exatas de tokens. Os logs da plataforma, no entanto, mostraram que cerca de doze por cento das buscas dos usuários não retornavam nada. Erros de ortografia como “intersteller” ou “avengrs endgame” – o tipo de erro que as pessoas cometem em teclados de dispositivos móveis – eram os principais culpados.

Uma solução rápida usando trigramas (fragmentos de três caracteres) reduziu a taxa de buscas vazias para 7%, mas introduziu dois problemas. Primeiro, o índice inflou para mais de três vezes o seu tamanho original, aumentando os custos de armazenamento e retardando as atualizações. Segundo, a relevância foi prejudicada; a correspondência aproximada (fuzzy matching) retornava uma mistura ruidosa de vídeos não relacionados, confundindo os usuários em vez de guiá-los.

A equipe concluiu que era necessário um mecanismo de busca dedicado, com tolerância nativa a erros de digitação e uma pontuação de relevância sofisticada.

Construindo o pipeline do OpenSearch

Mantenha o SQLite como a fonte da verdade

O OpenSearch serviu como uma réplica descartável e de apenas leitura. Todos os metadados dos vídeos permaneceram no SQLite; o índice de busca poderia ser reconstruído sem risco de perda de dados. Quando o cluster OpenSearch ficava offline, a aplicação retornava automaticamente para o mecanismo FTS5 original.

Relevância em camadas com uma consulta “should”

Em vez de depender apenas de correspondência aproximada (fuzzy matching), a consulta combinava três cláusulas:

  • Correspondência de frase exata – maior impulsionamento (boost), recompensando usuários que digitaram o título corretamente.
  • Todos os termos presentes – impulsionamento médio, capturando consultas onde cada palavra aparece, mas não necessariamente em ordem.
  • Correspondência aproximada (fuzzy match) – baixo impulsionamento, atuando como uma rede de segurança para tokens com erro de ortografia.

Essa hierarquia preservou a precisão para consultas limpas, ao mesmo tempo em que oferecia um recurso de contingência (fallback) tolerante a erros de digitação.

Ajustando as configurações de fuzzy

Um comprimento de prefixo de 1 forçou o primeiro caractere de cada termo a coincidir antes que a lógica fuzzy entrasse em ação. Essa regra manteve a busca rápida e evitou a explosão de termos candidatos que podem sobrecarregar a memória. A equipe também limitou o número máximo de expansões de termos, outra salvaguarda contra o uso desenfreado de recursos.

Estratégia de sincronização

Três processos complementares mantêm o índice do OpenSearch alinhado com o SQLite:

  • Um cron job para sincronizar novos dados.
  • Passagem de diferença (diff) noturna – verifica discrepâncias que passaram despercebidas pelas atualizações incrementais.
  • Reconstrução completa semanal – é executada por trás de um alias de índice e, em seguida, troca o alias em uma única operação, garantindo tempo de inatividade zero.

Impacto mensurável após duas semanas

  • Consultas sem resultados caíram de 12% para 1,4%.
  • A conversão de busca para clique aumentou em 9%.
  • A latência mediana permaneceu abaixo de 28 ms, bem dentro da meta de experiência do usuário da plataforma.