A backend project that demonstrates a microservices architecture using NestJS, RabbitMQ, Docker, PostgreSQL, and Prisma ORM. This project was built to showcase real-world backend architecture concepts such as event-driven systems, Saga pattern (Choreography), asynchronous processing, and distributed transaction management.
This project implements a microservices architecture with an API Gateway that orchestrates communication between services using both synchronous HTTP (for queries) and asynchronous events (for commands).
graph LR
Client[Client] -->|HTTP| GW[API Gateway]
GW -->|Events| RMQ[RabbitMQ]
GW -.->|HTTP| Order[Order Service]
GW -.->|HTTP| Payment[Payment Service]
RMQ <-->|Events| Order
RMQ <-->|Events| Payment
Order --> OrderDB[(PostgreSQL<br/>Order DB)]
Payment --> PaymentDB[(PostgreSQL<br/>Payment DB)]
style GW fill:#4A90E2,color:#fff
style RMQ fill:#FF6B35,color:#fff
style Order fill:#50C878,color:#fff
style Payment fill:#50C878,color:#fff
style OrderDB fill:#9B59B6,color:#fff
style PaymentDB fill:#9B59B6,color:#fff
- API Gateway: Single entry point for all client requests (port 3000)
- Event-Driven Commands: POST/PATCH operations emit events via RabbitMQ
- Synchronous Queries: GET operations make direct HTTP calls to microservices
- Saga Pattern (Choreography): Distributed transactions coordinated through events, with compensating actions for failures and cancellations
- Service Autonomy: Each microservice has its own database and business logic
- Decoupled Communication: Services communicate through events, not direct calls
payment-microservices/
βββ apps/
β βββ api-gateway/ # API Gateway (Port 3000)
β β βββ src/
β β βββ common/
β β β βββ http-client.helper.ts
β β βββ modules/
β β βββ orders/
β β β βββ dto/
β β β βββ orders.controller.ts
β β β βββ orders.service.ts
β β β βββ orders.module.ts
β β βββ payments/
β β βββ payments.controller.ts
β β βββ payments.service.ts
β β βββ payments.module.ts
β β
β βββ order-service/ # Order Microservice (Port 3001)
β β βββ prisma/
β β β βββ generated/
β β β βββ migrations/
β β β βββ prisma.module.ts
β β β βββ prisma.service.ts
β β β βββ schema.prisma
β β βββ src/
β β βββ modules/
β β βββ order/
β β βββ dto/
β β βββ order.consumer.ts
β β βββ order.controller.ts
β β βββ order.service.ts
β β
β βββ payment-service/ # Payment Microservice (Port 3002)
β βββ prisma/
β β βββ generated/
β β βββ migrations/
β β βββ prisma.module.ts
β β βββ prisma.service.ts
β β βββ schema.prisma
β βββ src/
β βββ modules/
β βββ payment/
β βββ dto/
β βββ payment.consumer.ts
β βββ payment.controller.ts
β βββ payment.service.ts
β
βββ libs/
β βββ contracts/ # Shared contracts
β β βββ events/ # Event definitions
β β β βββ order-created.event.ts
β β β βββ order-cancelled.event.ts
β β β βββ payment-approved.event.ts
β β β βββ payment-declined.event.ts
β β β βββ payment-failed.event.ts
β β βββ types/
β β βββ event-types.enum.ts
β β βββ cancel-reason.enum.ts
β β
β βββ messaging/ # Shared RabbitMQ module
β βββ rabbitmq/
β βββ config/
β βββ constants/
β βββ rabbitmq.module.ts
β βββ rabbitmq.service.ts
β
βββ docker-compose.yml
βββ README.md
- Single entry point for all client requests
- Routes queries (GET) directly to microservices via HTTP
- Emits events for commands (POST/PATCH) via RabbitMQ
- Centralized error handling and logging
- Request timeout and retry logic
- Manages order lifecycle (PENDING_PAYMENT β PAID β CANCELLED β FAILED)
- Consumes
order.create.requestedandorder.cancel.requestedevents to persist order state - Consumes
payment.approved,payment.declined,payment.failedevents to update order status - Emits
order.createdandorder.cancelledevents to trigger downstream reactions - RESTful API for order queries (GET endpoints)
- Isolated PostgreSQL database
- Manages payment lifecycle (PROCESSING β APPROVED / DECLINED / FAILED / REFUNDED / CANCELLED)
- Consumes
order.createdevent to initiate payment processing - Consumes
order.cancelledevent to cancel or refund payments in progress - Emits
payment.approved,payment.declined,payment.failedevents based on processing result - Simulates payment gateway integration with approval/decline logic
- Provides payment statistics and queries
- Isolated PostgreSQL database
- RabbitMQ for asynchronous messaging
- Dead Letter Queue (DLQ) for failed messages
- Event replay and idempotency handling
- Durable queues and persistent messages
- Happy path:
order.create.requestedβorder.createdβpayment.approvedβ order marked as PAID - Failure path:
payment.declined/payment.failedβ order marked as CANCELLED / FAILED - Compensating transaction:
order.cancel.requestedβorder.cancelledβ payment marked as CANCELLED or REFUNDED - No central coordinator β each service reacts to events and emits its own
| Technology | Purpose |
|---|---|
| NestJS | Backend framework for building scalable Node.js applications |
| TypeScript | Type-safe language for robust code |
| RabbitMQ | Message broker for event-driven architecture |
| PostgreSQL | Relational database for order and payment data |
| Prisma ORM | Type-safe database access and migrations |
| Docker | Containerization for consistent environments |
| Docker Compose | Multi-container orchestration |
- Node.js (v18+)
- Docker and Docker Compose
- npm or yarn
- Clone the repository
git clone https://github.com/luchersou/payment-microservice.git
cd payment-microservices- Install dependencies
npm install- Start services with Docker Compose
docker-compose up --buildAll requests go through the API Gateway on http://localhost:3000/api
| Method | Endpoint | Description |
|---|---|---|
POST |
/orders |
Create a new order (emits event) |
GET |
/orders |
Get all orders (paginated) |
GET |
/orders/:id |
Get order by ID |
PATCH |
/orders/:id |
Update order status (emits event) |
| Method | Endpoint | Description |
|---|---|---|
GET |
/payments |
Get all payments (paginated) |
GET |
/payments/:id |
Get payment by ID |
GET |
/payments/order/:orderId |
Get payment by order ID |
GET |
/payments/stats |
Get payment statistics by status |
1. Client β POST /api/orders
2. API Gateway β Emit order.create.requested β RabbitMQ
3. Order Service β Consume order.create.requested
- Generate orderId
- Persist order (status: PENDING_PAYMENT)
- Emit order.created β RabbitMQ
4. Payment Service β Consume order.created
- Create payment (status: PROCESSING)
- Simulate payment gateway
5. Payment Service β Emit:
- payment.approved
- OR payment.declined
- OR payment.failed
6. Order Service β Consume payment event
- Update order status:
- APPROVED β PAID
- DECLINED β CANCELLED
- FAILED β FAILED
1. Client β PATCH /api/orders/:id/cancel
2. API Gateway β Emit order.cancel.requested β RabbitMQ
3. Order Service β Consume order.cancel.requested
- Update order status β CANCELLED
- Emit order.cancelled β RabbitMQ
4. Payment Service β Consume order.cancelled
- If PROCESSING β Mark as CANCELLED
- If APPROVED β Mark as REFUNDED
POST http://localhost:3000/api/orders
Content-Type: application/json
{
"userId": "d55fa6d6-63c2-4633-aeaf-ecf0c80fb48f",
"total": 999
}cURL:
curl -X POST http://localhost:3000/api/orders \
-H "Content-Type: application/json" \
-d '{
"userId": "d55fa6d6-63c2-4633-aeaf-ecf0c80fb48f",
"total": 999
}'Response:
{
"orderId": "11c4a663-47fd-4590-9c2d-ee72cc58bbbd",
"message": "Order creation request accepted",
"status": "PENDING_PAYMENT"
}GET http://localhost:3000/api/orders?page=1&limit=10cURL:
curl http://localhost:3000/api/orders?page=1&limit=10Response:
{
"data": [
{
"id": "476f5730-aa83-4ff0-ab9f-d6e19836e195",
"userId": "d55fa6d6-63c2-4633-aeaf-ecf0c80fb48f",
"total": 999,
"status": "PAID",
"createdAt": "2026-02-15T01:42:19.000Z",
"updatedAt": "2026-02-15T01:42:21.000Z"
},
{
"id": "b7740f92-e574-4936-aa23-56f98ba61418",
"userId": "d55fa6d6-63c2-4633-aeaf-ecf0c80fb48f",
"total": 999,
"status": "CANCELLED",
"createdAt": "2026-02-15T01:42:39.000Z",
"updatedAt": "2026-02-15T01:42:40.000Z"
}
],
"meta": {
"page": 1,
"limit": 10,
"total": 2,
"totalPages": 1
}
}GET http://localhost:3000/api/orders/476f5730-aa83-4ff0-ab9f-d6e19836e195cURL:
curl http://localhost:3000/api/orders/476f5730-aa83-4ff0-ab9f-d6e19836e195Response:
{
"id": "476f5730-aa83-4ff0-ab9f-d6e19836e195",
"userId": "d55fa6d6-63c2-4633-aeaf-ecf0c80fb48f",
"total": 999,
"status": "PAID",
"createdAt": "2026-02-15T01:42:19.000Z",
"updatedAt": "2026-02-15T01:42:21.000Z"
}PATCH http://localhost:3000/api/orders/476f5730-aa83-4ff0-ab9f-d6e19836e195/cancelcURL:
curl -X PATCH http://localhost:3000/api/orders/476f5730-aa83-4ff0-ab9f-d6e19836e195 \
-H "Content-Type: application/json" \
-d '{"status": "CANCELLED"}'Response:
{
"orderId": "476f5730-aa83-4ff0-ab9f-d6e19836e195",
"message": "Order cancellation request accepted"
}GET http://localhost:3000/api/payments?page=1&limit=10cURL:
curl http://localhost:3000/api/payments?page=1&limit=10Response:
{
"data": [
{
"id": "8a5da4d7-3512-4c74-bd62-64b6c0e93e7a",
"orderId": "476f5730-aa83-4ff0-ab9f-d6e19836e195",
"amount": 999,
"status": "APPROVED",
"createdAt": "2026-02-15T01:42:19.500Z",
"updatedAt": "2026-02-15T01:42:20.500Z"
},
{
"id": "1220b65f-df5f-456d-8238-e03520bff097",
"orderId": "b7740f92-e574-4936-aa23-56f98ba61418",
"amount": 999,
"status": "DECLINED",
"createdAt": "2026-02-15T01:42:39.200Z",
"updatedAt": "2026-02-15T01:42:40.200Z"
}
],
"meta": {
"page": 1,
"limit": 10,
"total": 2,
"totalPages": 1
}
}GET http://localhost:3000/api/payments/8a5da4d7-3512-4c74-bd62-64b6c0e93e7acURL:
curl http://localhost:3000/api/payments/8a5da4d7-3512-4c74-bd62-64b6c0e93e7aResponse:
{
"id": "8a5da4d7-3512-4c74-bd62-64b6c0e93e7a",
"orderId": "476f5730-aa83-4ff0-ab9f-d6e19836e195",
"amount": 999,
"status": "APPROVED",
"createdAt": "2026-02-15T01:42:19.500Z",
"updatedAt": "2026-02-15T01:42:20.500Z"
}GET http://localhost:3000/api/payments/order/476f5730-aa83-4ff0-ab9f-d6e19836e195cURL:
curl http://localhost:3000/api/payments/order/476f5730-aa83-4ff0-ab9f-d6e19836e195Response:
{
"id": "8a5da4d7-3512-4c74-bd62-64b6c0e93e7a",
"orderId": "476f5730-aa83-4ff0-ab9f-d6e19836e195",
"amount": 999,
"status": "APPROVED",
"createdAt": "2026-02-15T01:42:19.500Z",
"updatedAt": "2026-02-15T01:42:20.500Z"
}GET http://localhost:3000/api/payments/statscURL:
curl http://localhost:3000/api/payments/statsResponse:
{
"byStatus": [
{
"status": "APPROVED",
"count": 2,
"totalAmount": 1998
},
{
"status": "DECLINED",
"count": 1,
"totalAmount": 999
}
]
}- Microservices Architecture: Independent services with isolated databases
- API Gateway Pattern: Single entry point for client requests
- Event-Driven Architecture: Asynchronous communication via RabbitMQ
- Saga Pattern (Choreography): Distributed transactions with compensating actions across services
This project is licensed under the MIT License.
Lucas Herzinger Souza
- GitHub: @luchersou