A high-throughput, event-driven e-commerce engine built with Node.js and Docker.
A decoupled, domain-driven backend for e-commerce workloads β designed to survive traffic spikes, avoid distributed monoliths, and stay debuggable in production.
- Architecture
- Key Features
- Architectural & Security Decisions
- Tech Stack
- Local Setup & Quickstart
- Testing & QA
- Roadmap
- Contributing
- License
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:
- Client β API Gateway β
Order Service(POST /orders) Order Servicevalidates cart contents againstCart Service(sync HTTP)Order Servicepersists the order and publishesorder.createdto RabbitMQCatalog Serviceconsumesorder.createdβ decrements stockNotification Serviceconsumesorder.createdβ sends confirmation email- All services emit structured logs to the ELK stack for tracing and alerting
| 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 |
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 /ordersandPOST /paymentsrequire anIdempotency-Keyheader, 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.
| 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 |
- Node.js
>= 20.x - Docker & Docker Compose
make(optional, for shortcut commands)
git clone https://github.com/your-org/scalable-ecommerce-microservices.git
cd scalable-ecommerce-microservicescp .env.example .envEdit .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=8500docker compose up --buildThis spins up: api-gateway, auth-service, catalog-service, cart-service, order-service, notification-service, postgres, redis, rabbitmq, consul, and the elk stack.
docker compose exec order-service npm run migrate
docker compose exec catalog-service npm run migratecurl 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 |
# 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:coverageCoverage reports are output to /coverage per service and aggregated in CI via codecov.
- 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
- Payment service with Stripe webhook reconciliation
- Saga-based distributed transaction rollback for failed payments
- Per-service rate limiting via Redis token buckets
- 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
Contributions are welcome! Please:
- Fork the repo and create a feature branch (
git checkout -b feature/my-feature) - Follow the existing code style (
npm run lintbefore committing) - Write or update tests for any behavioral change
- Open a PR with a clear description of the change and its motivation
See CONTRIBUTING.md for full guidelines and the Code of Conduct.
Distributed under the MIT License. See LICENSE for details.
Roadmap.sh Project URL Project_URL.
Built with β and a healthy fear of distributed systems.