Back to Case Studies

OnDelivery: the architecture behind the platform

How I structured OnDelivery: a monorepo, several NestJS and Express.js services, messaging with BullMQ and RabbitMQ and container-based delivery.

OnDelivery: the architecture behind the platform

1. Context & Engineering Challenge

Operational Context:

OnDelivery is the platform I build for restaurants and delivery businesses: orders, point of sale, deliveries, catalog, inventory, cash register, coupons, loyalty and an online store for customers, plus apps for waiters, couriers, the kitchen (KDS), kiosks and QR menus. I organized the code as a monorepo with several services. The backend uses NestJS and Express.js on PostgreSQL, with BullMQ and RabbitMQ for asynchronous processing; the front-ends are built with Next.js and React. Everything runs in containers, with tests and CI on GitHub Actions.

The Technical Bottleneck:

What demands the most attention in a platform like this: • Keeping clear boundaries between monorepo packages that share one repository and pipeline. • Coordinating contracts, configuration and data consistency across independent services. • Ensuring delivery, idempotency and traceability of messages between services. • Keeping container images lean, secure and reproducible.

2. Decisions

The architecture rests on four choices: • Monorepo: every package in one repository, with workspaces. • Several services: each service with its own code and container, orchestrated with Docker Compose. • Asynchronous messaging: BullMQ and RabbitMQ between services. • Containers: Dockerfiles and Docker Compose to build and run everything.

3. Architecture Topology & Flow

OnDelivery: the architecture behind the platform
Rendering architectural diagram...

4. Implementation & Design Patterns

Stack by layer: • Languages: TypeScript, Go and Python • Runtime: Node.js • Backend: NestJS, Express.js and WebSocket / Socket.io • Frontend: Next.js, React, Tailwind CSS and TanStack Query • Data: PostgreSQL with TypeORM, and Redis • Messaging: BullMQ and RabbitMQ • Validation: Zod • Testing: Jest, Vitest and Playwright • Delivery: Docker, GitHub Actions and NGINX • Observability: OpenTelemetry, Grafana, Prometheus, Loki and Tempo Delivery and quality: • The repository has tests with Jest, Vitest and Playwright, CI on GitHub Actions, Dockerfiles and a Docker Compose file.

5. Trade-offs & Conscious Compromises

• Monorepo: atomic changes across packages and shared tooling, but the pipeline and accidental coupling between packages need care. • Several services: each service deploys and scales on its own, at the cost of more operations, distributed observability and eventual consistency between them. • Asynchronous messaging: decouples services in time and absorbs load peaks, but debugging gets harder and consumers must be idempotent. • Containers: environment parity and predictable deploys, with the cost of keeping base images up to date.

6. Results

In this study I focus on the architecture. Usage metrics and results are for a future write-up.
Éverton Carvalho|Software Engineer | Software Architect | CTO

Built with Next.js 15, NestJS 11, PostgreSQL and Prisma. Decoupled, pragmatic architecture.

© 2026 Éverton Carvalho. Todos os direitos reservados.

Portfolio V2 · Zero Shared Runtimes