TixVibe Microservices is an advanced, distributed event-ticketing platform designed with the scalability, resilience, and efficiency needed to handle millions of users, built with best practices and patterns inspired by industry leaders like Google, Meta, Amazon, and Uber.
This project follows microservices architecture and modern distributed system principles to ensure reliability, scalability, and maintainability in a high-traffic environment. Key features include event-driven communication, eventual consistency, fault isolation, and a cloud-native deployment model. The platform leverages modern tools like Kubernetes, Docker, NATS Streaming, Redis, and Bull.js to handle the complexities of asynchronous communication and distributed job management.
- đź’Ž TixVibe Microservices Monorepo
- Table of Contents
- Introduction
- Architecture Overview
- Features
- Development and Deployment
- Testing and CI/CD
- Common Library (
@tixvibe/common
) - Installation and Running Instructions
- Links and References
- Screenshots
- Screenshots II
- Screenshots III
- Screenshots IV
TixVibe Microservices is built with a clear focus on delivering a high-performance, scalable platform capable of supporting millions of users. At its core, it adopts microservices architecture to decouple domains and scale independently while maintaining system reliability and performance under heavy traffic.
This project is driven by modern best practices in distributed systems and cloud-native technologies, integrating Kubernetes, Docker, Redis, Bull.js, and NATS Streaming to enable efficient service discovery, container orchestration, and asynchronous communication.
Key aspects of the design include:
- Optimistic Concurrency Control (OCC) to manage distributed transactions safely.
- Database-per-service approach to ensure domain isolation, which is key for scaling and fault tolerance.
- Event-driven architecture with NATS Streaming to ensure decoupled, asynchronous communication between services.
- A shared common library (
@tixvibe/common
) used across all services to ensure code consistency and reuse.
The architecture is designed around the following principles:
Each service is isolated with its own database and domain logic. This pattern, also known as Database-per-Service, ensures:
- Fault isolation: Failures in one service do not affect others.
- Independent scaling: Services can scale independently based on load and traffic.
- Independent deployments: New versions of services can be deployed independently without impacting others.
Services interact using HTTP for synchronous communication and NATS Streaming for asynchronous, event-driven communication. The use of NATS ensures:
- Loose coupling between services, allowing for easy extensibility and scalability.
- Eventual consistency in the system, as services handle events independently and asynchronously.
To provide consistency and flexibility, all services expose standardized REST APIs that:
- Use JSON as the data format, with fields such as
_id
parsed toid
for easier integration with NoSQL databases. - Return standardized error responses, which simplify handling errors in the frontend (Next.js).
For all services handling concurrent updates to critical resources (such as tickets or orders), we use Optimistic Concurrency Control (OCC). This approach helps:
- Mitigate race conditions in distributed systems.
- Safeguard data integrity by validating the state of resources before committing changes.
At the heart of TixVibe is an event-driven architecture that leverages NATS Streaming Server for reliable, asynchronous message passing between services. This approach allows decoupled communication, where services publish events and subscribe to others' events, enabling eventual consistency.
Each service implements a publisher to emit events and a listener to handle events emitted by other services. The events propagate business logic changes (e.g., a new ticket being created or an order being placed), ensuring that all services are eventually synchronized with the latest state.
The core of the event-driven system is the Base Publisher and Base Listener classes in the @tixvibe/common
library, which abstract:
- Event emission: Services can easily publish events without needing to manually set up listeners.
- Event subscription: Services can listen for specific events from other services, maintaining a reactive flow of information.
By ensuring that each service is responsible for emitting and handling events related to its domain, we achieve a highly decoupled architecture that can scale horizontally, with minimal impact on other services during failure or changes.
The use of Bull.js and Redis ensures that job expiration and retries are handled efficiently. Services can queue jobs (like ticket reservations) in Redis and retry them when necessary, ensuring reliability even under heavy load.
The microservices are structured around the One Database per Service pattern, where each service maintains its own database (MongoDB in this case). This approach ensures:
- Data isolation: No direct sharing of databases between services, promoting separation of concerns.
- Service independence: Each service can evolve and scale independently without needing to coordinate with other services' databases.
- Redundancy: Services can store relevant data in other services’ databases if required (for example, the
Orders
service stores ticket data).
Additionally, the project implements Optimistic Concurrency Control (OCC) to prevent race conditions in distributed transactions, especially when services perform operations on the same resource simultaneously.
A singleton pattern is used for managing single instances of critical components across the services:
- NATS Streaming Client: Each service shares the same instance of the NATS Streaming client, ensuring efficient communication without redundant connections.
- MongoDB: All database interactions use a singleton instance of the MongoDB connection to avoid connection pool overhead.
Although the system does not fully embrace Event Sourcing, the event-driven nature of the architecture ensures that key events (e.g., order created, ticket purchased) are stored and can be replayed for debugging or future processing.
- Microservice Scalability: Independent services that can scale based on demand.
- Event-Driven Architecture: Loose coupling of services via NATS Streaming, promoting flexibility and scalability.
- Optimistic Concurrency Control (OCC): Prevents race conditions when updating critical resources.
- Redis + Bull.js for Job Expiration and Retry Logic: Ensures smooth job execution and reliable expiration of resources.
- Load Balancing with NGINX Ingress: Facilitates effective HTTP traffic distribution across services in the Kubernetes cluster.
- Service Discovery with Kubernetes: Automatic service discovery and scaling using Kubernetes in both local and cloud environments.
For local development, Minikube provides an easy way to spin up a Kubernetes cluster on your machine:
- Start Minikube:
minikube start
- Configure hostfile:
Add the following line to your
/etc/hosts
file:<MINIKUBE_IP> tixvibe.dev
- Enable Ingress and Tunnel:
minikube addons enable ingress minikube tunnel
- Deploy Services using Skaffold:
skaffold dev
- Create Cluster:
gcloud container clusters create tixvibe-cluster --num-nodes=3
- Configure kubectl for GKE:
gcloud container clusters get-credentials tixvibe-cluster
- Deploy Services:
skaffold run
- Create Cluster:
eksctl create cluster --name tixvibe-cluster
- Configure kubectl for EKS:
aws eks update-kubeconfig --name tixvibe-cluster
- Deploy Services:
skaffold run
- Automated Unit Tests: Using Jest for writing unit and integration tests for services, listeners, and publishers.
- Mocked Testing: Includes mocked tests for NATS Streaming and Stripe integration to ensure service independence and testability
.
- CI/CD Pipeline: Integrates with GitHub Actions for automated deployment to GKE or AWS EKS.
The @tixvibe/common
library contains shared code for microservices, including:
- Base Publisher/Listener for event-driven communication with NATS Streaming.
- Utility functions for logging, error handling, and authentication.
- API DTOs and models for consistent data structures across services.
This shared library allows developers to focus on core business logic without duplicating infrastructure code across services.
-
Clone the repository:
git clone https://github.com/tixvibe/tixvibe-microservices.git cd tixvibe-microservices
-
Install dependencies:
npm install
-
Run services locally:
skaffold dev