Voltar para Estudos de Caso

Girowin: uma plataforma de jogos com dinheiro real

Como eu estruturei a plataforma do Girowin: serviços NestJS por domínio, carteira com ledger idempotente, mensageria com RabbitMQ e operação com várias réplicas.

Girowin: uma plataforma de jogos com dinheiro real

1. Contexto & Desafio de Engenharia

Cenário Operacional:

O Girowin é uma plataforma de jogos online com cassino, jogos originais, cassino ao vivo, carteira, promoções, afiliados e KYC, operada por um backoffice completo. Eu sou o CTO e construí a arquitetura e boa parte do backend. Numa plataforma assim, cada centavo precisa estar certo: o mesmo depósito não pode virar saldo duas vezes, uma aposta não pode ser debitada duas vezes e o histórico precisa fechar com o saldo, mesmo com provedores reenviando callbacks e filas reentregando mensagens.

O Gargalo / Problema Técnico:

Os problemas que guiaram a arquitetura: • Provedores de jogos e gateways de pagamento reenviam chamadas; a fila reentrega mensagens. • Muitas apostas concorrentes sobre a mesma carteira. • Jobs agendados rodando em várias réplicas ao mesmo tempo. • Integrações com exigências diferentes, inclusive IP fixo de saída. • Um backoffice que precisa enxergar tudo: financeiro, risco, KYC e CRM.

2. Decisões

As decisões principais: • Serviços por domínio: auth, casino, gaming, payment, affiliates, communication e CRM, num monorepo NestJS, cada um com o próprio banco PostgreSQL. • Crédito idempotente: cada crédito leva o id do movimento de origem como chave, e um reenvio devolve o recibo original. • Ledger da carteira, hoje em implantação: cada movimento grava saldo anterior e posterior na mesma transação que altera o saldo, com uma chave única por carteira, tipo e id externo. • Concorrência explícita: débitos de aposta com FOR UPDATE e saques com advisory lock por saque e recibo de débito. • Eventos entre serviços por RabbitMQ, com o cliente endurecido contra queda do canal. • Workers separados da API (papéis web e worker), com crons coordenados por lease no Redis. • Um proxy de saída com IP fixo para os provedores que exigem allowlist.

3. Topologia & Fluxo de Dados

Girowin: uma plataforma de jogos com dinheiro real
Rendering architectural diagram...

4. Implementação & Padrões

Organizei o backend como um monorepo NestJS com serviços por domínio: auth, casino, gaming, payment, affiliates, communication e CRM, além de workers que rodam crons e filas sem expor HTTP. Os front-ends falam REST com os serviços, o tempo real passa por Socket.IO e os serviços conversam entre si por RabbitMQ, como no crédito de um depósito confirmado na carteira. Stack por camada: • Backend: NestJS 11 em TypeScript, com um monorepo de serviços • Front-ends: Next.js 16, React 19, Tailwind 4, TanStack Query e Zustand • Dados: PostgreSQL com TypeORM, um banco por serviço • Cache e locks: Redis • Mensageria: RabbitMQ entre serviços e Bull para jobs • Tempo real: Socket.IO • Segurança: JWT em cookies HttpOnly, 2FA TOTP, KYC e rate limiting • Qualidade: Jest e Supertest, com regressão da carteira no CI (GitHub Actions) • Infra: Docker, NGINX e uma stack de observabilidade com OpenTelemetry, Prometheus, Loki, Tempo e Grafana Na prática: • Um depósito confirmado dispara o evento interno deposit.confirmed; o crédito vai ao gaming por RPC no RabbitMQ com o id do depósito como chave e é retentado com backoff. • Avisos ao jogador saem de um outbox transacional com FOR UPDATE SKIP LOCKED, lease e backoff exponencial. • No ledger, um job diário confere a cadeia e acusa qualquer buraco. • Callbacks de provedor são validados por HMAC-SHA256 sobre o corpo cru. • Sessões com tokens em hash SHA-256 e rotação de refresh token com detecção de reuso. • A regressão da carteira roda no CI contra um PostgreSQL real.

5. Trade-offs & Decisões Conscientes

O que essas escolhas cobram: • Um banco por serviço dá isolamento, mas leva a consistência eventual entre serviços e exige eventos bem desenhados. • O ledger com chave única elimina duplicidade, ao custo de mais escrita e de uma disciplina rígida de id externo em cada integração. • Locks e recibos protegem o saque, mas exigem uma ordem de locks rígida para não criar deadlocks. • Workers separados simplificam a escala da API, com a contrapartida de coordenar jobs entre réplicas. • Muitos serviços pedem uma boa observabilidade para depurar um fluxo que atravessa a fila.

6. Resultados

Os números de operação são confidenciais. Aqui eu foco na arquitetura e nas decisões que mantêm o dinheiro correto.
Éverton Carvalho|Software Engineer | Software Architect | CTO

Construído com Next.js 15, NestJS 11, PostgreSQL e Prisma. Arquitetura desacoplada e pragmática.

© 2026 Éverton Carvalho. Todos os direitos reservados.

Portfolio V2 · Zero Shared Runtimes