// event-driven order fulfillment, over RabbitMQ

Distributed order fulfillment,
coordinated asynchronously.

A production-style microservices backend that simulates e-commerce fulfillment. Orders come in, stock gets reserved, shipments are created with tracking numbers, and customers get notified — services never call each other, they just react to events.

5 services 1 topic exchange DB-per-service 80%+ test coverage
Architecture

A gateway, four services, one message bus

The API Gateway authenticates and fans out REST calls to four independent services. They never call each other directly — they coordinate by publishing and consuming events on a RabbitMQ topic exchange.

Client web · mobile · CLI HTTPS + JWT API Gateway JWT · RBAC · validation · proxy REST (X-User-Id / X-User-Role) Order orders · items status lifecycle Inventory products · stock reservations Shipping shipments tracking #s Notification mock email history log publish / consume RabbitMQ — topic exchange logistics.events · durable queues · DLX / DLQ · exponential-backoff retries
Features

Built like a real backend, not a toy

Every service owns its data, trusts the gateway, and recovers from failure on its own. The patterns below are the difference between a demo and something you'd actually run.

Event-Driven Choreography

Services coordinate through events, never direct calls. OrderCreated ripples through inventory, shipping, and notifications with no central orchestrator.

JWT Auth + RBAC

The gateway issues JWTs (bcrypt-hashed creds) and enforces roles. Internal services trust X-User-Id / X-User-Role headers — inventory management is ADMIN-only.

Idempotent Operations

Stock reservation and shipment creation are keyed on order_id, so a redelivered event never double-reserves stock or creates a duplicate shipment.

Dead-Letter Queues & Retries

Durable queues retry with exponential backoff, then dead-letter to a DLQ after MAX_RETRIES — poison messages are isolated, never silently dropped.

Cache-Aside with Redis

Hot reads are cached in Redis and invalidated on write. If the cache is down, requests degrade to a clean miss against Postgres rather than failing.

Database-per-Service

Each service owns a private PostgreSQL database (async SQLAlchemy 2.0 + asyncpg, migrated by Alembic). No shared tables, no hidden coupling.

Request-ID Tracing

Every event carries an envelope with a request-id, so a single order can be traced end-to-end across all four services and the message bus.

80%+ Test Coverage

Pytest suites cover services and event handlers, run in CI via GitHub Actions on every push — so refactors stay honest.

Event Flow

One order, traced across the mesh

Place an order and watch it propagate. The happy path completes a fulfillment; if stock runs out, the order branches cleanly into a cancellation.

Happy path order fulfilled
OrderCreatedOrder service
StockReservedInventory service
ShipmentCreatedShipping service
NotificationNotification service
Failure path insufficient stock
OrderCreatedOrder service
StockUnavailableInventory service
Order CANCELLEDOrder service
Tech Stack

Modern async Python, the whole way down

A pragmatic, production-leaning stack — fully containerized so the entire mesh comes up with one command.

FastAPI async SQLAlchemy 2.0 asyncpg PostgreSQL Redis RabbitMQ Alembic JWT + bcrypt Docker Compose Pytest GitHub Actions
Get Started

Up and running in three commands

Clone the repo, copy the example environment, and bring the whole mesh up with Docker Compose.

bash
# 1 — clone the repo
$ git clone https://github.com/jyotir07/ordermesh && cd ordermesh
# 2 — set up environment
$ cp .env.example .env
# 3 — bring the whole mesh up
$ docker-compose up --build
API Gateway
http://localhost:8000 — Swagger at /docs
RabbitMQ Management
http://localhost:15672 — queues, exchanges & DLQs