Building Booking Microservices with Express.js

Jan 30, 2024 | Programming

Welcome to the fascinating world of microservices! In this blog, we’ll explore how to create a robust infrastructure for distributed systems using modern technologies like Vertical Slice Architecture, Event Driven Architecture, and more. By the end of this guide, you’ll have a clear understanding of how to implement a microservices architecture with Node.js and Express.js.

Table of Contents

The Goals of This Project

This project aims to implement various advanced architectural principles to create a functioning microservices structure:

  • :sparkle: Utilizing Vertical Slice Architecture for a cleaner architecture level.
  • :sparkle: Leveraging RabbitMQ on top of AMQP for event-driven communication.
  • :sparkle: Adopting a data-centric architecture based on CRUD operations.
  • :sparkle: Implementing internal communication through REST using Axios.
  • :sparkle: Employing CQRS with the MediatrJs internal library.
  • :sparkle: Using Express as the web framework.
  • :sparkle: Storing data in a PostgreSQL database with TypeORM.
  • :sparkle: Managing dependency injections with Tsyringe.
  • :sparkle: Implementing authentication and authorization using Passport and JWT.
  • :sparkle: Enabling distributed tracing through OpenTelemetry.
  • :sparkle: Setting up monitoring systems with Prometheus and Grafana.
  • :sparkle: Validating inputs with Joi.
  • :sparkle: Organizing configuration with dotenv.
  • :sparkle: Conducting unit tests with Jest and integration tests with Testcontainers.
  • :sparkle: Using Swagger to generate API documentation automatically.

Plan

This project is a work in progress, with new features added over time. Future goals and additions can be found in the Issues section of this repository. Here’s a high-level plan of the features:

Feature Status
Identity Service Completed
Flight Service Completed
Passenger Service Completed
Booking Service Completed
Building Blocks Completed

Technologies – Libraries

We use a variety of modern technologies and libraries for this project, including:

  • TypeScript – A language for application-scale JavaScript.
  • Express – A fast and minimalist web framework for Node.js.
  • TypeORM – An ORM that simplifies database interactions.
  • amqplib – A library for AMQP 0-9-1 clients for Node.js.
  • Tsyringe – A lightweight dependency injection container for TypeScript.
  • Passport – Authentication middleware for Node.js.
  • OpenTelemetry – A toolkit for collecting metrics and traces.

The Domain and Bounded Context – Service Boundary

This system is organized into bounded contexts. Each service plays a distinct role:

  • Identity Service: Handles authentication and authorization.
  • Flight Service: Manages flight-related operations.
  • Passenger Service: Tracks passenger information and notifications.
  • Booking Service: Manages all booking-related operations.

Structure of Project

To implement a clean design, we combine clean architecture with vertical slice architecture. Each microservice is decoupled, communicates via REST or gRPC, and uses RabbitMQ for asynchronous messaging. The flow of requests follows a vertical slice approach, enhancing separation of concerns while ensuring easy maintainability.

Connecting these architectures can be thought of like this: imagine you’re building a city (your application) rather than a single building (a traditional app). Each neighborhood (microservice) has its own unique identity and functionality while still contributing to the overall city life. They communicate through roads (REST or gRPC) but operate independently, reducing dependencies. This model also allows you to build newer neighborhoods without having to completely renovate the entire city, focusing on enhancing specific parts rather than the whole.

How to Use Migrations

For migrations in TypeORM, handy scripts are provided in the package.json. To generate a new migration, use:

npm run migration:generate -- src/data/migrations/new-migration-name

To run migrations, execute:

npm run migration:run

How to Run

Docker Compose

To run the complete infrastructure using Docker, execute the following command:

docker-compose -f .deployments/docker-compose/infrastructure.yaml up -d

Build

To build each microservice, run this command:

npm run build

Run

To run a specific microservice, use:

npm run dev

Test

To test each microservice, run:

npm test

Documentation APIs

Each microservice includes Swagger OpenAPI for easy browsing of endpoints. For testing APIs, refer to the booking.rest file, which can be executed with the REST Client VSCode plugin.

Troubleshooting

If you encounter any issues while setting up the microservices, here are a few troubleshooting tips:

  • Ensure you have Docker installed and running properly.
  • Check if all necessary services are running by executing docker ps.
  • Look for any error messages in the console related to dependency installations.
  • If migrations fail, ensure your database is set up correctly and running.
  • For more insights, updates, or to collaborate on AI development projects, stay connected with fxis.ai.

Support

If you appreciate this project, don’t hesitate to star the repository. Your support motivates me to continue improving it!

Contribution

Thanks to all contributors for your invaluable input. Your help makes this project better! Please follow the contribution guideline to submit pull requests or create issues.

At fxis.ai, we believe that such advancements are crucial for the future of AI, as they enable more comprehensive and effective solutions. Our team is continually exploring new methodologies to push the envelope in artificial intelligence, ensuring that our clients benefit from the latest technological innovations.

Happy coding and building robust applications!

Stay Informed with the Newest F(x) Insights and Blogs

Tech News and Blog Highlights, Straight to Your Inbox