Pular para o conteúdo

Case study de engenharia

Um bot simples
por fora. Um sistema real por dentro.

O NekoMoji foi projetado, desenvolvido e operado de ponta a ponta por Gabriel. Esta é a leitura técnica de um produto que processou mídia, pagamentos e mensagens para 37 mil pessoas — com decisões de arquitetura, confiabilidade, privacidade e custo tomadas em produção.

message-lifecycle.ts

receive(signedWebhook)

↓ validate · normalize · route

guard(identity, limits, premium)

↓ download · transcode · compress

send(orderedSticker)

↓ correlate · aggregate · observe

✓ delivered · without storing content
produto + backend + operação

A base privada em números

Complexidade conquistada, não inventada.

Ordens de grandeza registradas no encerramento. Os números do produto foram auditados; os números de código representam o repositório em outubro de 2026.

800+

commits

da ideia ao encerramento

100+

módulos TypeScript

separados por domínio

120+

arquivos de teste

unitários e de integração

7

integrações sociais

em um pipeline comum

37.293pessoas atendidas

405.531figurinhas entregues

2.576pagamentos aprovados

O repositório do NekoMoji permanece privado. Ele contém histórico operacional, configurações e informações ainda confidenciais. Este case publica arquitetura, decisões e resultados suficientes para avaliação técnica sem expor código ou dados sensíveis.

Jornada de infraestrutura

Da AWS à VPS: arquitetura também é economia.

A infraestrutura mudou junto com o estágio do produto. Primeiro, velocidade. Depois, previsibilidade de custo. Por fim, automação e controles para uma operação madura conduzida por uma pessoa.

  1. 01

    Agosto–setembro de 2025

    Validar antes de otimizar

    A primeira infraestrutura usou serviços da AWS para colocar o produto no ar rapidamente. O objetivo era reduzir o tempo entre ideia e uso real, mesmo com custo ainda pouco previsível.

    time-to-market
  2. 02

    Outubro de 2025

    Migrar para caber no projeto

    A operação foi levada para uma VPS Hostinger pré-paga por dois anos. A troca reduziu a incerteza mensal e transformou infraestrutura em uma despesa conhecida — importante para um projeto pessoal.

    FinOps
  3. 03

    Novembro de 2025–março de 2026

    Assumir a própria operação

    Linux, Nginx, TLS, PM2, domínio, processos e backups passaram a fazer parte do produto. A migração para a Cloud API adicionou webhooks, filas e novas fronteiras de falha.

    SRE solo
  4. 04

    Abril–setembro de 2026

    Automatizar para sobreviver

    CI, branch protegida, releases, deploy, health checks e rollback reduziram o risco operacional. Portas ficaram restritas, serviços internos foram isolados e a saúde passou a ser verificada depois de cada entrega.

    defesa em profundidade

Arquitetura em camadas

Da mensagem recebida ao resultado observado.

O sistema evoluiu para fronteiras claras: transporte, orquestração, domínio, persistência e operação. Isso permitiu mudar uma parte sem reescrever a conversa inteira.

Entrada

WhatsApp Cloud API + Express

01

Webhooks assinados recebiam mensagens e status da Meta. O servidor respondia rápido e encaminhava o evento para o pipeline sem acoplar HTTP à regra de negócio.

  • Meta Cloud API
  • Express
  • HMAC
  • webhooks

Orquestração

Pipeline de mensagens

02

Guardas, cadastro, comandos, limites, links Premium e mídia seguiam uma ordem explícita. Cada domínio tinha handlers próprios, mantendo contratos públicos estáveis durante as refatorações.

  • TypeScript
  • ESM
  • handlers
  • rate limits

Processamento

Mídia adaptativa

03

Imagens, vídeos e GIFs passavam por validação, recorte, compressão e metadados. Vídeos difíceis usavam prévia, escada adaptativa e circuit breaker para evitar consumo inútil de CPU.

  • FFmpeg
  • ffprobe
  • sharp
  • WebP mux

Estado e negócio

Firestore + Mercado Pago

04

Usuário unificado, uso, Premium, indicação e histórico conviviam com cache e consultas indexadas. Pagamentos eram validados no provedor e processados de forma idempotente.

  • Firestore
  • Admin SDK
  • Mercado Pago
  • idempotência

Saída

Adapter central da Meta

05

Texto, menus, figurinhas e reações saíam por um único ponto. Isso permitiu instrumentar tentativas, aceites, falhas, tipos e jornadas sem espalhar telemetria por cada fluxo.

  • fila outbound
  • categorias fixas
  • retries
  • backpressure

Operação

Métricas, saúde e deploy

06

Agregados diários, health checks e relatórios ligavam comportamento técnico a uso, receita e custo. Releases versionadas passavam por CI, deploy automatizado e rollback com verificação de saúde.

  • Vitest
  • GitHub Actions
  • PM2
  • Nginx

Ciclo de uma interação

Uma conversa era um fluxo distribuído.

O usuário via poucos segundos de espera. O backend precisava coordenar identidade, regras, serviços externos, CPU, entrega e telemetria.

  1. 1

    Webhook

    assinatura e envelope

  2. 2

    Roteamento

    comando, link ou mídia

  3. 3

    Guardas

    usuário, grupo, limite e Premium

  4. 4

    Execução

    download ou conversão

  5. 5

    Entrega

    fila, upload e mensagem

  6. 6

    Observação

    aceite, status e agregado

Caminho feliz

Receber → validar → reservar uso → processar → enviar em ordem → confirmar entrega.

Falha recuperável

Retry com backoff → fallback → erro sanitizado → rollback do uso → métrica por categoria.

Regra financeira

Criar preferência → persistir pendência → validar webhook → deduplicar → ativar → invalidar cache.

Estado, dinheiro e confiança

As partes que não podiam falhar em silêncio.

O NekoMoji precisava reconhecer a mesma pessoa em identidades diferentes, conceder exatamente o que foi pago e medir o produto sem transformar conversas em dados de telemetria.

Dados e identidade

De registros simples a um usuário unificado

O Firestore entrou ainda no primeiro mês. Com o crescimento, telefone, JID e identificadores da Cloud API precisaram convergir sem duplicar pessoas, Premium ou limites.

  • contadores atômicos e locks de uso
  • índices, cache e manutenção por consulta
  • mapeamentos de identidade e migrações compatíveis
  • expiração de Premium e checkout sem varrer a base inteira

Pagamentos

Premium simples para o usuário, rigoroso no backend

O checkout pelo Mercado Pago escondia um fluxo distribuído: preferência, pendência, webhook, consulta ao provedor, ativação e reconciliação. Repetir um evento nunca poderia repetir um benefício.

  • PIX e checkout sem assinatura recorrente
  • assinatura de webhook e consulta ao provedor
  • idempotência por pagamento e referência externa
  • reconciliação, expiração, reembolso e trilha mínima

LGPD e segurança

Privacidade tratada como requisito de arquitetura

A adequação não ficou restrita a uma política. Ela chegou aos logs, ao banco, às referências financeiras, à telemetria, aos backups e aos procedimentos de atendimento ao titular.

  • consentimento antes de analytics
  • exportação, exclusão e retenção operacional
  • logs sanitizados e referências opacas
  • artefatos temporários, HMAC e TTL

Decisões e trade-offs

Engenharia é escolher onde colocar a complexidade.

As escolhas abaixo nasceram de problemas observados, não de arquitetura por antecipação.

Trocar sessão por API oficial

Contexto:
A primeira versão dependia de uma sessão conectada ao WhatsApp. Era simples para começar, mas frágil para operar.
Decisão:
Migrar para a WhatsApp Cloud API, com webhooks assinados, adaptação de envelopes e envio centralizado.
Resultado:
Mais previsibilidade e segurança — em troca de maior custo, limites externos e complexidade operacional.

Idempotência antes da mutação

Contexto:
Webhooks financeiros podem repetir, atrasar ou chegar depois de um reinício. Cache em memória não era garantia suficiente.
Decisão:
Consultar o histórico persistido por paymentId e external_reference antes de ativar ou estender o Premium.
Resultado:
O retry continuou seguro sem conceder duas vezes o mesmo benefício, mesmo após perda do cache do processo.

Concorrência baixa, ordem preservada

Contexto:
Uma publicação social podia produzir várias mídias. Paralelizar tudo elevava CPU; serializar tudo piorava a espera.
Decisão:
Processar com concorrência máxima pequena e enviar os resultados na ordem original, agregando falhas parciais.
Resultado:
Um meio-termo explícito entre latência, previsibilidade, custo de CPU e experiência na conversa.

Métrica útil sem conteúdo do usuário

Contexto:
Era necessário entender custo e entrega, mas texto, telefone e mídia não deveriam virar telemetria.
Decisão:
Usar categorias e jornadas fixas, agregados diários e HMAC temporário do identificador da Meta com TTL.
Resultado:
Foi possível medir funis e falhas sem guardar a mensagem, o número, o arquivo ou o identificador bruto.

Automação como multiplicador de uma pessoa

Contexto:
Código, produto, suporte e infraestrutura estavam com o mesmo mantenedor. Operação manual não escalaria.
Decisão:
Transformar lint, tipos, testes, release, deploy, health check, manutenção e relatórios em rotinas reproduzíveis.
Resultado:
Menos dependência de memória humana e mudanças menores, rastreáveis e reversíveis.

Encerramento em profundidade

Contexto:
Parar o handler não bastava: uma conversão iniciada antes do corte ainda poderia terminar depois dele.
Decisão:
Bloquear o serviço no handler, no registro de transporte e no adapter final de envio, preservando só a mensagem final idempotente.
Resultado:
A regra de negócio foi garantida em três fronteiras, inclusive para trabalho assíncrono já em andamento.

Operar também era construir

Confiabilidade para um time de uma pessoa.

Sem equipes separadas de SRE, dados, segurança ou suporte, o sistema precisava tornar o estado visível e o caminho de recuperação repetível.

Resiliência

Retries com backoff, circuit breakers para FFmpeg e integrações, slow mode, locks de uso e rollback quando a geração falhava.

Observabilidade

Health check, snapshots, alertas, desempenho de mídia e séries de tentativas, aceites, entregas e falhas por jornada.

Qualidade

Typecheck, ESLint e Vitest como gate; testes comportamentais protegiam ordem do pipeline, pagamentos, limites e regressões.

Entrega contínua

Branch protegida, PR, CI, release versionada, tag, deploy por GitHub Actions, PM2 e rollback se o health check não passasse.

Eficiência de dados

Caches explícitos e manutenção Premium por queries, evitando varrer dezenas de milhares de usuários na rotina diária.

Privacidade

Logs sanitizados, Firestore fechado para clientes, exportação e exclusão LGPD e telemetria agregada sem conteúdo pessoal.

Rastreabilidade de produção

Tentativa, aceite e entrega eram métricas diferentes.

A telemetria separava o que o bot tentou, o que a Meta aceitou e o que chegou a um desfecho terminal. Receita oficial vinha do Mercado Pago, não de eventos internos.

attemptedo adapter iniciou o envio
accepteda API retornou um wamid
delivered / readcallback terminal correlacionado
failedcódigo técnico, sem conteúdo

Engenharia AI-native, com governança

IA como multiplicador. Responsabilidade como limite.

O projeto atravessou um ano de evolução acelerada dos modelos. Em vez de apostar em um único fornecedor, virou um laboratório prático para comparar raciocínio, geração de código, revisão e automação.

A rastreabilidade não estava em “qual IA escreveu qual linha”, mas no que realmente importa em engenharia: requisito versionado, diff revisável, teste reproduzível, decisão humana e resultado observado.

ChatGPTOpenAI CodexCursorClaudeGitHub CopilotDeepSeekGrok

AI_01

Múltiplos modelos

ChatGPT e Codex, Claude, DeepSeek, Grok e outros modelos foram usados como pares diferentes para explorar, criticar e comparar soluções — nunca como uma única fonte de verdade.

AI_02

Ferramentas no fluxo

Cursor, Codex, GitHub Copilot e Claude Code conviveram com instruções compartilhadas, regras específicas por ferramenta e contexto técnico versionado no repositório.

AI_03

Contexto como código

AGENTS.md, regras do Cursor, ponte para Claude, instruções do Copilot, skills e runbooks registravam comandos, áreas sensíveis e critérios de aceite.

AI_04

Validação humana

A IA acelerava investigação, testes, documentação e refatorações. A decisão final continuava humana e precisava sobreviver a lint, tipos, testes, revisão, CI e validação em produção.

O ciclo de confiança

1Definir
2Planejar
3Construir
4Verificar
5Revisar
6Entregar

O que a produção ensinou

Os melhores aprendizados vieram dos limites.

LESSON_01

Aceito não significa entregue

A resposta 200 da Meta provava aceite, não chegada ao usuário. O monitor passou a correlacionar sent, delivered, read e failed, inclusive fora de ordem.

LESSON_02

Média esconde o incidente

Um percentual global parecia saudável enquanto uma categoria de figurinha animada concentrava falhas. Segmentar por tipo e jornada tornou a causa acionável.

LESSON_03

O banco também é parte do produto

Modelo de usuário, índices, TTL, deduplicação e manutenção query-based determinaram custo e confiabilidade tanto quanto o código do bot.

LESSON_04

Documentação é infraestrutura

Fluxos críticos, runbooks, decisões e procedimentos de rollback reduziram o risco de um sistema operado por uma única pessoa.

LESSON_05

Sustentabilidade é requisito técnico

Custos por mensagem, CPU de mídia, volume de suporte e receita foram tratados como partes do desenho — e não apenas como uma planilha posterior.

LESSON_06

Saber encerrar também é engenharia

O desligamento exigiu data de corte, defesa em profundidade, idempotência, reconciliação financeira e comunicação compatível com o estado real do sistema.

Engenharia com responsabilidade de produto

Do primeiro commit ao último pacote entregue.

O NekoMoji reuniu arquitetura de soluções, backend, mídia, pagamentos, dados, segurança, observabilidade, DevOps, IA aplicada, suporte e estratégia de sustentabilidade sob a responsabilidade de um único engenheiro.