Voltar para Projetos

OnDelivery

Plataforma de delivery e gestão para restaurantes, com vários serviços em NestJS e Express.js, front-ends em Next.js e mensageria com BullMQ e RabbitMQ.

OnDelivery

Visão Geral do Sistema

O OnDelivery é a plataforma que eu desenvolvo para restaurantes e deliveries: pedidos, PDV, entregas, catálogo, estoque, caixa, cupons, fidelidade e uma loja online para o cliente final, além de apps para garçom, entregador, cozinha (KDS), totem e cardápio QR. Organizei o código como um monorepo com vários serviços. O backend usa NestJS e Express.js sobre PostgreSQL, com BullMQ e RabbitMQ no processamento assíncrono; os front-ends são em Next.js e React. Tudo roda em contêineres, com testes e CI no GitHub Actions.

Desafios de Engenharia & Gargalos

O que mais exige atenção numa plataforma assim: • Manter claras as fronteiras entre os pacotes do monorepo, mesmo com repositório e pipeline compartilhados. • Coordenar contratos, configuração e consistência de dados entre serviços independentes. • Garantir entrega, idempotência e rastreabilidade das mensagens entre os serviços. • Manter as imagens de contêiner enxutas, seguras e reproduzíveis.

Arquitetura da Solução & Padrões

Organizei o OnDelivery como um monorepo com vários pacotes de workspace. Cada serviço é construído a partir do próprio código e orquestrado com Docker Compose, e a comunicação assíncrona entre eles passa por BullMQ e RabbitMQ. Stack por camada: • Linguagens: TypeScript, Go e Python • Runtime: Node.js • Backend: NestJS, Express.js e WebSocket / Socket.io • Frontend: Next.js, React, Tailwind CSS e TanStack Query • Dados: PostgreSQL com TypeORM e Redis • Mensageria: BullMQ e RabbitMQ • Validação: Zod • Testes: Jest, Vitest e Playwright • Entrega: Docker, GitHub Actions e NGINX • Observabilidade: OpenTelemetry, Grafana, Prometheus, Loki e Tempo Mapa do sistema: Estes são os componentes do OnDelivery, agrupados por área. Deixei de fora endereços, URLs internas e credenciais. • Entrada: nginx e vps-private-bridge • Serviços: commerce, payment, subscription, communication, evolution-api, affiliates, auth, catalog, procurement e sefaz • Dados: commerce-db, auth-db, scheduling-db, services-db, evolution-service, db, cache (Redis), rabbitmq e Postgres-PITR • Observabilidade: grafana, prometheus, loki, tempo, otel-collector, cadvisor e node-exporter

Mapa do sistema

Arquitetura do OnDelivery

Os apps, a entrada, os serviços NestJS e o que cada um usa. As setas mostram como as partes se comunicam; os serviços conversam entre si por RabbitMQ.

flowchart LR
  subgraph fe["Front-ends"]
    sellers["Painel, PDV, KDS, garçom e totem (Next.js, PWA)"]
    web["Loja online (Next.js)"]
    qr["Cardápio QR (Next.js)"]
    native["App de garçom, entregador e maquininha (Expo)"]
    desk["App de impressão (Electron)"]
  end
  subgraph entry["Entrada"]
    bff["BFF do Next: cookie HttpOnly"]
    nginx["NGINX"]
  end
  subgraph svc["Serviços NestJS"]
    commerce["commerce: pedidos, estoque, caixa, KDS"]
    auth["auth"]
    payment["payment"]
    subs["subscription"]
    comm["communication: WhatsApp, e-mail, SMS"]
    proc["procurement: notas fiscais"]
    sefaz["sefaz: emissor fiscal"]
    others["catalog, affiliates e scheduling"]
  end
  subgraph data["Dados e mensageria"]
    pg[("PostgreSQL: um banco por serviço")]
    mq["RabbitMQ"]
    bull[("Redis: filas Bull")]
    cache[("Redis: cache")]
  end
  subgraph ext["Integrações"]
    paygw["Gateways de pagamento"]
    sefazext["SEFAZ"]
    wa["WhatsApp"]
  end
  obs["Observabilidade: OpenTelemetry e Grafana"]
  sellers -->|REST| bff
  web -->|REST| bff
  bff -->|Bearer| nginx
  qr -->|REST| nginx
  native -->|REST| nginx
  desk -->|REST| nginx
  nginx --> svc
  commerce -.->|SSE| bff
  svc --> mq
  mq -->|impressão| desk
  proc -->|REST| sefaz
  sefaz -->|XML assinado| sefazext
  commerce --> bull
  comm --> bull
  svc --> pg
  commerce --> cache
  payment --> paygw
  subs --> paygw
  comm --> wa
  svc -.->|OTLP| obs
  class commerce,auth,payment,subs,comm,proc,sefaz,others tech-nestjs
  class pg tech-postgresql
  class mq tech-rabbitmq
  class bull,cache tech-redis
  class nginx tech-nginx

Do pedido à cozinha, à impressora e à nota fiscal

O caminho de um pedido: o pagamento é confirmado por webhook, o pedido aparece em tempo real no painel e no KDS, o cupom sai na impressora e a NFC-e é emitida.

flowchart LR
  client["Cliente na loja online"] -->|checkout| commerce["commerce"]
  commerce -->|link de pagamento| mq["RabbitMQ"]
  mq --> payment["payment"]
  payment --> gw["Gateway de pagamento"]
  gw -->|webhook| payment
  payment -->|pedido pago| mq
  mq --> commerce
  commerce -.->|SSE| panel["Painel e KDS"]
  commerce -->|impressão| mq
  mq --> printer["App de impressão"]
  commerce -->|emitir NFC-e| mq
  mq --> proc["procurement"]
  proc -->|REST| sefaz["sefaz"]
  sefaz -->|XML assinado| sefazext["SEFAZ"]
  commerce -->|aviso| comm["communication: WhatsApp"]
  class commerce,payment,proc,sefaz,comm tech-nestjs
  class mq tech-rabbitmq

Mapa do sistema — visão geral (parte 1)

Os componentes de cada área. Dividi a visão geral em partes para caber em telas pequenas; ao ampliar a primeira, aparece o mapa inteiro com as ligações entre os componentes.

flowchart TB
  %% kind: system-map
  %% "~~~" lines are invisible layout hints, not links
  accTitle: Mapa do sistema — visão geral (parte 1)
  accDescr: Componentes do OnDelivery agrupados por área.
  subgraph aEntry["Entrada"]
    direction TB
    m1["     nginx                      (proxy · NGINX)"]
    m2["vps‑private‑    bridge      (ponte)   "]
    m1 ~~~ m2
  end
  subgraph aServices["Serviços"]
    direction TB
    m3["commerce            (serviço)  NestJS  "]
    m4[" payment            (serviço)  NestJS  "]
    m5["subscription               (serviço)      NestJS   "]
    m6["communication                 (serviço)      NestJS    "]
    m7["evolution‑api   (serviço) "]
    m8["affiliates   (serviço)"]
    m9["   auth      (serviço)"]
    m10["  catalog    (serviço)"]
    m11["procurement  (serviço)"]
    m12["   sefaz     (serviço)"]
    m3 ~~~ m5
    m4 ~~~ m6
    m5 ~~~ m7
    m6 ~~~ m8
    m7 ~~~ m9
    m8 ~~~ m10
    m9 ~~~ m11
    m10 ~~~ m12
  end
  aEntry ~~~ aServices
  class m1 tech-nginx
  class m3,m4,m5,m6 tech-nestjs

Mapa do sistema — visão geral (parte 2)

flowchart TB
  %% kind: system-map
  %% "~~~" lines are invisible layout hints, not links
  accTitle: Mapa do sistema — visão geral (parte 2)
  accDescr: Componentes do OnDelivery agrupados por área.
  subgraph aData["Dados"]
    direction TB
    m13[("commerce‑db              (banco de    dados)    PostgreSQL ")]
    m14[(" auth‑db              (banco de    dados)   PostgreSQL")]
    m15[("scheduling‑db                 (banco de      dados)      PostgreSQL  ")]
    m16[("services‑db              (banco de    dados)    PostgreSQL ")]
    m17[("evolution‑  service              (banco de    dados)   PostgreSQL")]
    m18[("    db                   (banco de    dados)    PostgreSQL")]
    m19[("     cache                      (cache · Redis)")]
    m20[" rabbitmq                 (fila)     RabbitMQ"]
    m21[(" Postgres‑PITR  (armazenamento)  ")]
    m13 ~~~ m15
    m14 ~~~ m16
    m15 ~~~ m17
    m16 ~~~ m18
    m17 ~~~ m19
    m18 ~~~ m20
    m19 ~~~ m21
  end
  class m13,m14,m15,m16,m17,m18 tech-postgresql
  class m19 tech-redis
  class m20 tech-rabbitmq

Mapa do sistema — visão geral (parte 3)

flowchart TB
  %% kind: system-map
  %% "~~~" lines are invisible layout hints, not links
  accTitle: Mapa do sistema — visão geral (parte 3)
  accDescr: Componentes do OnDelivery agrupados por área.
  subgraph aObservability["Observabilidade"]
    direction TB
    m22["  grafana    (observa‑   bilidade)    Grafana"]
    m23["prometheus   (observa‑   bilidade)  Prometheus"]
    m24["   loki      (observa‑   bilidade)     Loki"]
    m25["   tempo     (observa‑   bilidade)     Tempo"]
    m26["otel‑collector   (observa‑      bilidade)    OpenTelemetry    Collector  "]
    m27[" cadvisor    (observa‑   bilidade)   cAdvisor"]
    m28["node‑exporter   (observa‑     bilidade)   Node Exporter "]
    m22 ~~~ m24
    m23 ~~~ m25
    m24 ~~~ m26
    m25 ~~~ m27
    m26 ~~~ m28
  end

Mapa do sistema — Entrada

Por onde as requisições entram e com o que cada componente se conecta. Uma caixa tracejada é a outra ponta da ligação, com a área entre parênteses; (área inteira) é uma ligação com a área toda.

flowchart LR
  %% kind: system-map-detail entry
  accTitle: Mapa do sistema — Entrada
  accDescr: Componentes do OnDelivery agrupados por área.
  m1["     nginx                      (proxy · NGINX)"]
  m2["vps‑private‑    bridge      (ponte)   "]
  r1["   Serviços    (área inteira)"]:::ref
  m1 --- r1
  classDef ref fill:none,stroke-dasharray:4 3
  class m1 tech-nginx

Mapa do sistema — Serviços (parte 1)

Os serviços e as suas ligações. Uma caixa tracejada é a outra ponta da ligação, com a área entre parênteses; (área inteira) é uma ligação com a área toda e (nesta área) marca outro serviço da mesma área. Um serviço com muitas ligações pode aparecer em mais de uma parte.

flowchart LR
  %% kind: system-map-detail services
  accTitle: Mapa do sistema — Serviços (parte 1)
  accDescr: Componentes do OnDelivery agrupados por área.
  m3["commerce            (serviço)  NestJS  "]
  m4[" payment            (serviço)  NestJS  "]
  m5["subscription               (serviço)      NestJS   "]
  class m3,m4,m5 tech-nestjs

Mapa do sistema — Serviços (parte 2)

flowchart LR
  %% kind: system-map-detail services
  accTitle: Mapa do sistema — Serviços (parte 2)
  accDescr: Componentes do OnDelivery agrupados por área.
  m6["communication                 (serviço)      NestJS    "]
  m7["evolution‑api   (serviço) "]
  m8["affiliates   (serviço)"]
  r1["evolution‑api (nesta área) "]:::ref
  m6 --- r1
  classDef ref fill:none,stroke-dasharray:4 3
  class m6 tech-nestjs

Mapa do sistema — Serviços (parte 3)

flowchart LR
  %% kind: system-map-detail services
  accTitle: Mapa do sistema — Serviços (parte 3)
  accDescr: Componentes do OnDelivery agrupados por área.
  m9["   auth      (serviço)"]
  m10["  catalog    (serviço)"]
  m11["procurement  (serviço)"]

Mapa do sistema — Serviços (parte 4)

flowchart LR
  %% kind: system-map-detail services
  accTitle: Mapa do sistema — Serviços (parte 4)
  accDescr: Componentes do OnDelivery agrupados por área.
  m12["   sefaz     (serviço)"]
  aSelf["   Serviços    (área inteira)"]:::wholeArea
  r1["  nginx   (Entrada)"]:::ref
  r2["    Dados      (área inteira)"]:::ref
  aSelf --- r1
  aSelf --- r2
  classDef ref fill:none,stroke-dasharray:4 3
  classDef wholeArea font-weight:bold

Mapa do sistema — Dados (parte 1)

Bancos, cache, fila e armazenamento, e com o que cada um se conecta. Uma caixa tracejada é a outra ponta da ligação, com a área entre parênteses; (área inteira) é uma ligação com a área toda.

flowchart LR
  %% kind: system-map-detail data
  accTitle: Mapa do sistema — Dados (parte 1)
  accDescr: Componentes do OnDelivery agrupados por área.
  m13[("commerce‑db              (banco de    dados)    PostgreSQL ")]
  m14[(" auth‑db              (banco de    dados)   PostgreSQL")]
  class m13,m14 tech-postgresql

Mapa do sistema — Dados (parte 2)

flowchart LR
  %% kind: system-map-detail data
  accTitle: Mapa do sistema — Dados (parte 2)
  accDescr: Componentes do OnDelivery agrupados por área.
  m15[("scheduling‑db                 (banco de      dados)      PostgreSQL  ")]
  m16[("services‑db              (banco de    dados)    PostgreSQL ")]
  class m15,m16 tech-postgresql

Mapa do sistema — Dados (parte 3)

flowchart LR
  %% kind: system-map-detail data
  accTitle: Mapa do sistema — Dados (parte 3)
  accDescr: Componentes do OnDelivery agrupados por área.
  m17[("evolution‑  service              (banco de    dados)   PostgreSQL")]
  m18[("    db                   (banco de    dados)    PostgreSQL")]
  class m17,m18 tech-postgresql

Mapa do sistema — Dados (parte 4)

flowchart LR
  %% kind: system-map-detail data
  accTitle: Mapa do sistema — Dados (parte 4)
  accDescr: Componentes do OnDelivery agrupados por área.
  m19[("     cache                      (cache · Redis)")]
  m20[" rabbitmq                 (fila)     RabbitMQ"]
  class m19 tech-redis
  class m20 tech-rabbitmq

Mapa do sistema — Dados (parte 5)

flowchart LR
  %% kind: system-map-detail data
  accTitle: Mapa do sistema — Dados (parte 5)
  accDescr: Componentes do OnDelivery agrupados por área.
  m21[(" Postgres‑PITR  (armazenamento)  ")]
  aSelf["    Dados      (área inteira)"]:::wholeArea
  r1["   Serviços    (área inteira)"]:::ref
  aSelf --- r1
  classDef ref fill:none,stroke-dasharray:4 3
  classDef wholeArea font-weight:bold

Mapa do sistema — Observabilidade (parte 1)

A stack de observabilidade: métricas, logs e traces.

flowchart LR
  %% kind: system-map-detail observability
  accTitle: Mapa do sistema — Observabilidade (parte 1)
  accDescr: Componentes do OnDelivery agrupados por área.
  m22["  grafana    (observa‑   bilidade)    Grafana"]
  m23["prometheus   (observa‑   bilidade)  Prometheus"]

Mapa do sistema — Observabilidade (parte 2)

flowchart LR
  %% kind: system-map-detail observability
  accTitle: Mapa do sistema — Observabilidade (parte 2)
  accDescr: Componentes do OnDelivery agrupados por área.
  m24["   loki      (observa‑   bilidade)     Loki"]
  m25["   tempo     (observa‑   bilidade)     Tempo"]

Mapa do sistema — Observabilidade (parte 3)

flowchart LR
  %% kind: system-map-detail observability
  accTitle: Mapa do sistema — Observabilidade (parte 3)
  accDescr: Componentes do OnDelivery agrupados por área.
  m26["otel‑collector   (observa‑      bilidade)    OpenTelemetry    Collector  "]
  m27[" cadvisor    (observa‑   bilidade)   cAdvisor"]

Mapa do sistema — Observabilidade (parte 4)

flowchart LR
  %% kind: system-map-detail observability
  accTitle: Mapa do sistema — Observabilidade (parte 4)
  accDescr: Componentes do OnDelivery agrupados por área.
  m28["node‑exporter   (observa‑     bilidade)   Node Exporter "]

Artefatos de entrega no repositório

Onde ficam os workflows de CI, os Dockerfiles e o Docker Compose no repositório.

flowchart TB
  nRepo["Repositório Git"]
  subgraph sgAssets["Artefatos de entrega"]
    direction LR
    nCi(["Configuração de CI"])
    nDocker["Definições de contêiner"]
    nCompose["Arquivo de orquestração de contêineres"]
  end
  nRepo -->|contém| sgAssets

Stack Tecnológica

TypeScript(backend)
Node.js(backend)
NestJS(backend)
Next.js(frontend)
React(frontend)
Tailwind CSS(frontend)
TanStack Query(frontend)
PostgreSQL(database-messaging)
TypeORM(database-messaging)
Arquitetura de Microsserviços(architecture)
Express.js(backend)
Redis(database-messaging)
RabbitMQ(database-messaging)
Background Jobs(backend)
Arquitetura Orientada a Eventos(architecture)
Docker(cloud-devops)
Docker Compose(cloud-devops)
Nginx(cloud-devops)
GitHub Actions(cloud-devops)
Object Storage (S3)(cloud-devops)
Observabilidade & Monitoramento(cloud-devops)
É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