Skip to content

Latest commit

Β 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ›’ Scalable E-Commerce Microservices

A high-throughput, event-driven e-commerce engine built with Node.js and Docker.

License Build Status Version Node Docker PRs Welcome

A decoupled, domain-driven backend for e-commerce workloads β€” designed to survive traffic spikes, avoid distributed monoliths, and stay debuggable in production.


πŸ“– Table of Contents


πŸ— Architecture / High-Level Design

The system is composed of independently deployable services communicating over REST (synchronous) for client-facing queries and RabbitMQ (asynchronous) for cross-service side effects (inventory decrement, email receipts, analytics events). Each service owns its own data β€” there is no shared database.

                                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                   β”‚   API Gateway /     β”‚
                                   β”‚   Nginx (Edge)       β”‚
                                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                              β”‚
                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                     β”‚                        β”‚                        β”‚
             β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
             β”‚  Auth Service  β”‚       β”‚  Catalog Service β”‚      β”‚  Cart Service    β”‚
             β”‚  (Node/Express)β”‚       β”‚  (Node/Express)  β”‚      β”‚  (Node/Express)  β”‚
             β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚                        β”‚                        β”‚
             β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
             β”‚  PostgreSQL    β”‚       β”‚  PostgreSQL      β”‚      β”‚  Redis           β”‚
             β”‚  (users)       β”‚       β”‚  (products)      β”‚      β”‚  (cart sessions) β”‚
             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                     β”‚                RabbitMQ (Event Bus)               β”‚
                     β”‚  order.created Β· payment.confirmed Β· stock.low   β”‚
                     β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚                             β”‚
                     β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”             β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”
                     β”‚ Order Service  β”‚             β”‚ Notification   β”‚
                     β”‚ (Node/Express) β”‚             β”‚ Service        β”‚
                     β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜             β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚                             β”‚
                     β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”             β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”
                     β”‚  PostgreSQL    β”‚             β”‚  SMTP / Push    β”‚
                     β”‚  (orders)      β”‚             β”‚  Provider       β”‚
                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                     β”‚        Consul (Service Discovery & Health)        β”‚
                     β”‚        ELK Stack (Centralized Logging/Metrics)   β”‚
                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Request flow example β€” placing an order:

  1. Client β†’ API Gateway β†’ Order Service (POST /orders)
  2. Order Service validates cart contents against Cart Service (sync HTTP)
  3. Order Service persists the order and publishes order.created to RabbitMQ
  4. Catalog Service consumes order.created β†’ decrements stock
  5. Notification Service consumes order.created β†’ sends confirmation email
  6. All services emit structured logs to the ELK stack for tracing and alerting

✨ Key Features & Domain Modules

Module Description
πŸ” Auth & Identity JWT-based auth with refresh token rotation, role-based access control (RBAC)
πŸ“¦ Product Catalog Full-text search, faceted filtering, category trees, stock-aware pricing
πŸ›’ Cart Service Redis-backed ephemeral carts with TTL, guest-to-user cart merging
πŸ’³ Checkout & Orders Idempotent order creation, saga-based payment orchestration
πŸ”” Notifications Async, queue-driven email/push notifications decoupled from the request path
πŸ“Š Observability Centralized structured logging, request tracing, and health dashboards
βš™οΈ Service Discovery Consul-based dynamic registration β€” no hardcoded service URLs
🚦 Rate Limiting Per-user and per-IP throttling at the gateway layer

🧠 Architectural & Security Decisions

Notable, non-obvious engineering choices and the reasoning behind them:

  • UUIDv7 over auto-increment IDs. All public-facing resource identifiers (orders, users, products) use UUIDv7 rather than sequential integers. This prevents IDOR enumeration attacks (/orders/1043 β†’ /orders/1044) while retaining timestamp-sortable ordering for efficient indexing, unlike random UUIDv4.
  • Event-driven decoupling over synchronous chaining. Side effects that don't need to block the response (stock updates, emails, analytics) are published to RabbitMQ instead of being called via HTTP. This keeps the checkout critical path fast and prevents cascading failures β€” if the Notification Service is down, orders still succeed.
  • Cache-aside strategy for the Catalog Service. Product reads hit Redis first; on a miss, Postgres is queried and the result is written back with a short TTL. Writes invalidate the specific cache key rather than flushing broad prefixes, minimizing thundering-herd risk.
  • No shared database across services. Each service owns its schema exclusively, accessed only through its own API. This trades some query convenience for genuine deployability independence and blast-radius containment.
  • Idempotency keys on write endpoints. POST /orders and POST /payments require an Idempotency-Key header, stored with a short TTL, so retried requests (client timeouts, network blips) never create duplicate orders or double-charge a customer.
  • Secrets never baked into images. All credentials are injected via environment variables at runtime (see .env.example) and are never committed or baked into Docker layers.

🧰 Tech Stack

Layer Technology
Runtime Node.js 20.x, Express
Database PostgreSQL 16 (per-service schemas)
Cache / Sessions Redis 7
Messaging / Events RabbitMQ
Service Discovery Consul
Monitoring / Logging ELK Stack (Elasticsearch, Logstash, Kibana)
Containerization Docker, Docker Compose
Auth JWT, bcrypt
Testing Jest, Supertest, Testcontainers
CI/CD GitHub Actions

πŸš€ Local Setup & Quickstart

Prerequisites

  • Node.js >= 20.x
  • Docker & Docker Compose
  • make (optional, for shortcut commands)

1. Clone the repository

git clone https://github.com/your-org/scalable-ecommerce-microservices.git
cd scalable-ecommerce-microservices

2. Configure environment variables

cp .env.example .env

Edit .env and set the required values:

# --- Core ---
NODE_ENV=development
PORT=3000

# --- Database ---
POSTGRES_USER=ecommerce
POSTGRES_PASSWORD=changeme
POSTGRES_DB=ecommerce_dev

# --- Cache ---
REDIS_URL=redis://redis:6379

# --- Messaging ---
RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672

# --- Auth ---
JWT_SECRET=replace-with-a-long-random-string
JWT_REFRESH_SECRET=replace-with-another-long-random-string

# --- Service Discovery ---
CONSUL_HOST=consul
CONSUL_PORT=8500

3. Start the stack

docker compose up --build

This spins up: api-gateway, auth-service, catalog-service, cart-service, order-service, notification-service, postgres, redis, rabbitmq, consul, and the elk stack.

4. Run database migrations

docker compose exec order-service npm run migrate
docker compose exec catalog-service npm run migrate

5. Verify it's alive

curl http://localhost:3000/health
# β†’ {"status":"ok","services":["auth","catalog","cart","order","notification"]}
Service Local URL
API Gateway http://localhost:3000
Kibana (logs) http://localhost:5601
Consul UI http://localhost:8500
RabbitMQ Management http://localhost:15672

πŸ§ͺ Testing & QA

# Run all unit tests across every service
npm run test:unit

# Run integration tests (spins up Testcontainers for Postgres/Redis/RabbitMQ)
npm run test:integration

# Run end-to-end tests against a running docker compose stack
docker compose -f docker-compose.test.yml up -d
npm run test:e2e

# Full CI-equivalent run (lint + unit + integration)
npm run test:ci

# Generate a coverage report
npm run test:coverage

Coverage reports are output to /coverage per service and aggregated in CI via codecov.


πŸ—Ί Development Roadmap

βœ… MVP (Shipped)

  • Auth service with JWT + refresh token rotation
  • Product catalog with search & filtering
  • Redis-backed cart with guest merging
  • Order creation with idempotency keys
  • Event-driven stock decrement via RabbitMQ
  • Centralized logging via ELK
  • Dockerized local development environment

🚧 In Progress

  • Payment service with Stripe webhook reconciliation
  • Saga-based distributed transaction rollback for failed payments
  • Per-service rate limiting via Redis token buckets

πŸ”­ Planned

  • GraphQL gateway as an alternative to REST aggregation
  • Kubernetes Helm charts for production deployment
  • Multi-region read replicas for the Catalog Service
  • Admin dashboard (React) for order & inventory management
  • OpenTelemetry distributed tracing across all services

🀝 Contributing

Contributions are welcome! Please:

  1. Fork the repo and create a feature branch (git checkout -b feature/my-feature)
  2. Follow the existing code style (npm run lint before committing)
  3. Write or update tests for any behavioral change
  4. Open a PR with a clear description of the change and its motivation

See CONTRIBUTING.md for full guidelines and the Code of Conduct.


πŸ“„ License

Distributed under the MIT License. See LICENSE for details.


πŸ“‚ Project URL

Roadmap.sh Project URL Project_URL.


Built with β˜• and a healthy fear of distributed systems.

About

Scalable, event-driven e-commerce microservices platform built with Node.js, Docker, Consul, RabbitMQ, Redis, and the ELK stack. Designed with a focus on high throughput, zero-trust security (UUID v7/IDOR protection), and automated CI/CD.

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors