DeployedEngineering Case Study

Melo.

Engineering a real-time communication platform with distributed services, event-driven messaging, and production infrastructure.

Role

Full-stack development

Architecture

Distributed services

Backend

Node.js · TypeScript

Infrastructure

Docker · Google Cloud

An end-to-end engineering project covering application development, backend architecture, service communication, containerization, deployment, and operational reliability.

01 / Overview

More than a chat application.

Building the features is only one part of the problem. The rest is designing how the services, data, and infrastructure work together.

Melo is a real-time communication platform built with a TypeScript-based stack. It supports messaging workflows, conversations, group interactions, file sharing, reactions, and mentions.

The project evolved beyond a single backend application into a service-oriented system. Authentication, application responsibilities, and messaging are separated, with dedicated communication mechanisms and supporting infrastructure.

I worked across the application stack, from implementing features and data access to containerizing the services, deploying the application, troubleshooting production issues, and introducing operational visibility.

Project scope

  • Application

    Real-time messaging and user interactions

  • Backend

    TypeScript services and data access

  • Communication

    gRPC, RabbitMQ, and Socket.IO

  • Infrastructure

    Docker Compose, Nginx, Google Cloud

  • Operations

    Health checks, logs, and metrics in auth-service

02 / System architecture

Separate responsibilities. Define clear boundaries.

Melo brings together application services, synchronous service communication, asynchronous events, persistent storage, and real-time infrastructure.

Frontend

Next.js · React · TypeScript

User interface for real-time communication.

Nginx

Reverse proxy · HTTPS

Entry point for routing external traffic to application services.

Backend services

Node.js · Express · gRPC

Application logic, authentication, messaging, and inter-service communication.

Data and messaging

PostgreSQL · MongoDB · Redis · RabbitMQ

Persistence, fast-access state, real-time presence, and asynchronous events.

Communication and data flow

Request / response

gRPC

Synchronous communication between services.

Event delivery

RabbitMQ

Asynchronous messaging between producers and consumers.

Live interactions

Socket.IO + Redis

Real-time communication and distributed presence.

System visualization

Architecture Diagram

A deployment-level view of Melo's services, communication paths, coordination infrastructure, and persistent data stores.

Conceptual architecture summary. It describes the principal components and communication patterns, not a complete deployment-level topology or every request path.

03 / Engineering decisions

Why the system is designed this way.

A useful architecture is not just a collection of technologies. Each component should have a clear responsibility and a reason to exist.

DECISION 01

Service separation

Implementation

Separate authentication and messaging responsibilities instead of putting every concern into a single application module.

Rationale

Explicit service boundaries make responsibilities easier to reason about and establish clearer interfaces between components.

DECISION 02

Synchronous and asynchronous communication

Implementation

Use gRPC for service-to-service request/response communication and RabbitMQ for event-driven workflows.

Rationale

These communication patterns serve different purposes: direct service calls when a response is required, and message-based processing for asynchronous events.

DECISION 03

Polyglot persistence

Implementation

Use PostgreSQL and MongoDB for different data requirements, with Redis for caching and fast-access state.

Rationale

Different storage technologies provide different data models and operational characteristics. Their use should follow the needs of each service rather than forcing everything into one database.

DECISION 04

Externalized runtime configuration

Implementation

Configure services through environment variables and coordinate local services through Docker Compose.

Rationale

Service configuration must match its execution environment. A container cannot use localhost to reach a different container; it needs the appropriate service hostname and port.

Data and state management

PostgreSQL and MongoDB serve different persistence requirements. Redis supports caching and fast-access state, including distributed presence. These components are not interchangeable: durable data, cached values, and transient coordination state have different consistency and lifecycle requirements.

04 / Production deployment

From local development to a deployed system.

The deployment work connected application code with the infrastructure needed to run it outside the development environment.

01

Prepare the production environment

Provision an Ubuntu virtual machine on Google Cloud and install the required runtime and container tooling.

02

Containerize the application

Build service images and define the application infrastructure with Docker Compose, including the relevant supporting services.

03

Configure traffic routing

Use Nginx as the reverse proxy and configure domain routing and HTTPS for the deployed application.

04

Automate releases

Use the GitHub Actions deployment workflow to automate the production build and release process.

Infrastructure stack

Ubuntu 24.04Google Cloud VMDockerDocker ComposeNginxHTTPSGitHub Actions

Continuous deployment

Deployment Pipeline

An overview of Melo's deployment workflow, from code changes and CI/CD automation to containerized services running in the production environment.

Container orchestration, reverse proxy configuration, network connectivity, environment variables, permissions, and service readiness all influence whether the deployed application works correctly. Production verification therefore extends beyond successfully building the images or starting the containers.

05 / Reliability and observability

Making service behavior easier to investigate.

The application needs more than successful requests. When something goes wrong, the system should provide useful signals to support diagnosis.

01

Health checks

Health-check mechanisms help verify whether application services are responding as expected.

02

Structured error handling

Consistent error handling makes application failures easier to understand and prevents expected failure paths from becoming opaque debugging problems.

03

Structured logging with Pino

Pino-based structured logging in the auth service provides machine-readable operational events that are easier to filter and investigate.

04

Metrics endpoint

The auth service exposes a metrics endpoint to provide an entry point for monitoring service behavior.

Current implementation scope

Pino structured logging and the metrics endpoint have been added to the authentication service. Health checks and structured error handling are part of the reliability work. This does not imply that centralized log aggregation, distributed tracing, alerting, or comprehensive metrics instrumentation across every service have been implemented.

06 / Testing and maintainability

Designing code that can be verified.

Maintainable backend systems need testable boundaries, explicit dependencies, and predictable failure behavior.

TESTING

Vitest

Vitest is used for authentication-service tests, including service logic, authentication middleware, OTP behavior, and controller flows. Mocking external dependencies helps isolate the behavior being tested.

CODE DESIGN

Repository pattern and dependency injection

The authentication module uses repository abstractions and dependency injection to separate application logic from persistence implementations. This makes dependencies more explicit and enables isolated tests.

Test coverage and passing status should be assessed from the current test run. A test suite is valuable only when its assertions are meaningful and the failures are understood.

07 / Lessons learned

What building and operating Melo taught me.

The most valuable part of the project was learning how application code, service boundaries, and infrastructure interact when the system is running.

01

A running container is not proof of a healthy application

Container status, service readiness, application health, and end-to-end functionality are different signals. Each must be verified at the appropriate layer.

02

Configuration is part of the architecture

Network addresses, environment variables, ports, permissions, and service dependencies can break a deployment even when the application code is correct.

03

Observability should answer operational questions

Logs and metrics are most useful when they help identify what happened, which component was involved, and where further investigation is needed.

04

Production debugging requires a systematic approach

Inspect the failing layer, gather evidence, isolate the cause, apply a targeted fix, and verify the result instead of making unrelated configuration changes.

08 / Technology stack

The tools behind Melo.

The stack spans application development, data persistence, inter-service communication, testing, and deployment.

Node.js
TypeScript
Express
PostgreSQL
MongoDB
Redis
RabbitMQ
gRPC
Socket.IO
Vitest
Pino
Docker
Docker Compose
Nginx
GitHub Actions
Google Cloud

End of case study

Built to understand the entire system, not just the code.

Melo brought together full-stack development, backend architecture, asynchronous communication, infrastructure, and production troubleshooting in one end-to-end engineering project.