Case de Engenharia

Novo Portal Gazeta Machadense

Reconstrução do portal de notícias: um backend monolítico modular em Java servindo portal, admin e app.

Java 21 / Spring Boot 3.3PostgreSQLRedisMeilisearchNext.jsFlutterFirebase AuthStripe Connect
New Gazeta Machadense Portal

A Gazeta Machadense precisava reconstruir seu ecossistema de notícias (~500 mil acessos/mês) com um backend único que servisse três frontends — portal, painel administrativo e app — sem cair na complexidade operacional de microsserviços, com um time pequeno (1–3 devs). Os desafios: manter os domínios isolados e coesos, ter busca rápida, atender dois públicos de autenticação (leitor e staff) e respeitar exigências legais do jornalismo, como retratação.

New Gazeta Machadense Portal

Três frontends (portal Next.js, admin React, app Flutter) consomem um único backend monolítico modular; PostgreSQL é a fonte da verdade, com Redis e Meilisearch ao lado, e integrações externas para mídia, pagamento, identidade e monitoramento.

  1. 01
    Monolito modular, não microsserviços (ADR-001)

    Um deploy único dividido em 11 módulos de domínio que só dependem de um módulo shared — nenhum módulo de domínio depende de outro. Eles conversam por Spring Application Events (@TransactionalEventListener, após o commit) ou por interfaces publicadas em shared. Resultado: latência interna ~zero e transações ACID atravessando contextos, com a fronteira garantida pela própria estrutura de pacotes. Escolha consciente para um time de 1–3 devs.

  2. 02
    Hexagonal pragmático por módulo

    Cada módulo (iam, content, media, publishing, ads, billing, newsletter, comments, analytics, search) segue sempre o mesmo corte: domain → repository → service → api → mapper. O módulo é a fronteira, sem ports/adapters cerimoniais — quem aprende um, aprende todos, e um módulo pode ser extraído como microsserviço no futuro.

  3. 03
    Borda comum em shared

    Tudo que é transversal vive em shared: BaseEntity (ID em ULID, timestamps, auditoria), tratamento de erro em Problem+JSON (RFC 7807), envelope HTTP, paginação por cursor (base64 de {published_at, id}) e correlação de request (MDC/RequestId). Os módulos não reinventam o básico.

  4. 04
    Dois fluxos de autenticação por path (ADR-005)

    Públicos diferentes, segurança diferente: /api/v1/public/* atende leitores via Firebase Auth (token opcional, perfil espelhado na tabela users); /api/v1/admin/* atende o staff via Spring Security 6 + JWT próprio, com RBAC granular e refresh tokens em Redis.

  5. 05
    Decisões com trade-off explícito (ADRs)

    As escolhas pesadas viram ADRs, cada uma amarrada ao problema que resolve: PostgreSQL como fonte da verdade; cursor pagination em vez de offset (o feed cresce e offset duplica registros); virtual threads porque a carga é I/O-bound; e soft delete porque retratação jornalística tem risco legal.

Integrações externas

Além do núcleo, o portal integra Meilisearch para busca, Cloudflare (R2/Images/Stream) para mídia, Stripe + Connect para pagamento e split, Firebase Admin para a identidade dos leitores e Sentry para monitoramento de erros — cada um isolado atrás do seu módulo.

O resultado é um backend único, simples de operar para um time pequeno, mas com a disciplina de fronteira de um sistema modular: domínios isolados que conversam por eventos, busca rápida, dois fluxos de autenticação e a porta aberta para extrair qualquer módulo como microsserviço quando — e se — fizer sentido. Um só deploy serve portal, admin e app.

0k+acessos/mês no ecossistema
0módulos de domínio

Vamos conversar sobre seu projeto?

Próximo caseGuia Gazeta Machadense