Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/astrxnomo/shop-microservers/llms.txt

Use this file to discover all available pages before exploring further.

Shop Microservers is designed around the principle that each service owns its domain completely — its own codebase, its own database, and its own process. No service reaches into another service’s data store. Cross-service coordination happens exclusively over the internal Docker network using well-defined HTTP APIs, with the Nginx gateway acting as the only component exposed to the outside world. This separation makes it straightforward to reason about, test, or replace any single service without touching the rest of the system.

Topology

The following diagram shows how every component in the platform connects:
                       ┌─────────────────┐
                       │  Nginx Gateway  │  :80
                       └────────┬────────┘
            ┌───────────┬───────┼─────────┬───────────┐
            │           │       │         │           │
        ┌───▼──┐   ┌────▼───┐   │   ┌─────▼──┐   ┌────▼─────┐
        │ auth │   │catalog │   │   │  cart  │   │  orders  │
        │ 3004 │   │  3001  │   │   │  3002  │   │   3003   │
        └───┬──┘   └────┬───┘   │   └────┬───┘   └────┬─────┘
            │           │       │        │            │
       ┌────▼────┐  ┌───▼────┐  │   ┌────▼────┐  ┌────▼────┐
       │orders_db│  │catalog │  │   │  redis  │  │orders_db│
       └─────────┘  │   db   │  │   └─────────┘  └─────────┘
                    └────────┘  │
                       ┌────────▼────────┐
                       │ frontend (Next) │  :3000
                       └─────────────────┘

Nginx gateway

The Nginx gateway is the sole public entry point for the entire platform, listening on port 80 (configurable via GATEWAY_PORT). It uses Docker’s internal DNS resolver (127.0.0.11) to look up upstream service addresses by their Compose service names, with a 30-second TTL. Every inbound request is matched against a location block and proxied to the appropriate upstream — the /api/<service>/ prefix is stripped before the request reaches the service, so services always receive paths relative to their own router roots. The location block assignments are:
LocationUpstreamNotes
/api/auth/auth:3004Standard HTTP proxy
/api/catalog/catalog:3001Standard HTTP proxy
/api/cart/cart:3002Standard HTTP proxy
/api/orders/orders:3003Standard HTTP proxy
/frontend:3000Includes Upgrade / Connection headers for WebSocket support
/healthReturns 200 ok directly from Nginx; used by its own Docker healthcheck
The frontend location block sets proxy_set_header Upgrade $http_upgrade and proxy_set_header Connection 'upgrade', which enables WebSocket connections — required for Next.js hot-module replacement during development.

Services

Auth — auth:3004

The auth service is an Express application backed by Prisma and a dedicated PostgreSQL 16 instance (auth_db). It exposes endpoints for user registration and login, and issues JWTs signed with the shared JWT_SECRET environment variable. Tokens carry a 7-day expiry. Every other service that requires authentication validates incoming Authorization: Bearer <token> headers against the same secret — there is no token introspection endpoint; validation is purely local to each service.

Catalog — catalog:3001

The catalog service is an Express application backed by Prisma and its own PostgreSQL 16 instance (catalog_db). It stores the Product table and serves product listings to the frontend via the gateway. On startup, it runs an idempotent seed script that inserts 12 products if the table is empty. It also exposes an internal PATCH /:id/stock endpoint used exclusively by the orders service to decrement stock after a successful checkout — this endpoint is not exposed through the gateway.

Cart — cart:3002

The cart service is a lightweight Express application that stores cart data entirely in Redis 7. Each user’s cart is a JSON array keyed by userId with a 7-day TTL — when the TTL expires or the orders service explicitly clears the cart after checkout, the key is simply deleted. There is no SQL database involved. All cart endpoints require a valid Bearer JWT, which the service verifies using the shared JWT_SECRET.

Orders — orders:3003

The orders service is an Express application backed by Prisma and a dedicated PostgreSQL 16 instance (orders_db). It orchestrates the entire checkout flow in a single request: it reads the user’s cart from the cart service, verifies that each product has sufficient stock by calling the catalog service, decrements stock for every line item, writes the Order and OrderItem rows to its own database, and finally asks the cart service to clear the user’s cart. All orders endpoints require a valid Bearer JWT. The service only starts after both the cart and catalog services pass their health checks.

Network

All containers — databases, microservices, gateway, and frontend — are connected to a single Docker bridge network named shop. Services address each other using their Compose service name as the hostname (e.g., catalog, cart, redis). No service port is published to the host except the gateway’s port 80. The frontend never calls any backend service directly; every API call goes through the gateway on the shop network.

Data storage

StoreTechnologyTables / KeysPersistence
catalog_dbPostgreSQL 16ProductNamed Docker volume (catalog_db_data)
auth_dbPostgreSQL 16UserNamed Docker volume (auth_db_data)
orders_dbPostgreSQL 16Order, OrderItemNamed Docker volume (orders_db_data)
Redis 7Redis 7Cart JSON keyed by userIdIn-memory only — no AOF/RDB persistence
Running docker compose down -v removes all named volumes, wiping every database and all Redis data. This is the recommended way to fully reset the development environment.

Health checks

Every service exposes a GET /health endpoint that returns 200 OK. Docker Compose uses these endpoints to gate startup ordering — the gateway will not start until all four microservices are healthy, and the orders service will not start until both catalog and cart are healthy. The Nginx gateway has its own health check that hits http://localhost/health, which is handled directly by the Nginx config without proxying to any upstream.
ServiceHealth check URLIntervalRetries
authhttp://localhost:3004/health15 s5
cataloghttp://localhost:3001/health15 s5
carthttp://localhost:3002/health15 s5
ordershttp://localhost:3003/health15 s5
frontendhttp://localhost:300020 s5
gatewayhttp://localhost/health15 s5

Inter-service communication

Direct service-to-service calls occur only within the orders service, which needs to coordinate across two other domains at checkout time. The URLs are injected via environment variables in docker-compose.yml:
CATALOG_URL=http://catalog:3001
CART_URL=http://cart:3002
All other communication between the frontend and the backend flows through the Nginx gateway. The shop Docker bridge network provides DNS resolution for these hostnames automatically — no service discovery sidecar or external registry is required.
Every route in the system returns a consistent response envelope:
{ "success": true, "data": { ... }, "error": null }
On failure, success is false, data is null, and error contains the error message. This convention applies to all four microservices.

Build docs developers (and LLMs) love