api-gateway) that handles JWT validation and request routing. Services communicate with each other over HTTP using RestTemplate; there is no message broker in the current architecture, with the exception of Spring ApplicationEvent used within the JVM for the notification pattern.
Service map
| Service | Port | Role | Database |
|---|---|---|---|
api-gateway | 8080 | JWT validation, routing, header injection | — |
auth-service | 8081 | User registration, login, token issuance | auth_db (PostgreSQL) |
ms-inventario | 8082 | Product catalog and stock management | inventario_db (PostgreSQL) |
ms-pedidos | 8083 | Order creation and lifecycle | pedidos_db (PostgreSQL) |
ms-envios | 8084 | Shipment tracking and carrier selection | envios_db (PostgreSQL) |
notification-service | 8085 | Receives and dispatches event notifications | — |
frontend | 5173 (80 in container) | React single-page application | — |
Microservices
api-gateway
The single entry point for all client traffic. Runs Spring Cloud Gateway MVC on port 8080. Validates JWTs on every protected route, injects the caller’s email as
X-User-Email, and strips the /api prefix before proxying to downstream services. Auth routes (/api/auth/**) bypass JWT validation.auth-service
Handles user registration and login on port 8081. Issues HMAC-SHA JWTs with a 24-hour expiration (
jwt.expiration=86400000 ms). Shares the same JWT_SECRET environment variable as the gateway so tokens can be verified without a round-trip.ms-inventario
Manages the product catalog and stock levels on port 8082. Exposes a REST API consumed directly by the frontend (via the gateway) and by
ms-pedidos during order placement. Protected by the gateway’s AuthFilter.ms-pedidos
Manages the full order lifecycle on port 8083. Calls
ms-inventario over HTTP to verify and reserve stock. A Resilience4j circuit breaker wraps that call so that inventory outages degrade gracefully rather than cascading into order failures.ms-envios
Tracks shipments and selects carriers on port 8084. Uses a Factory Method to instantiate the correct shipment handler (
TERRESTRE or EXPRESS) at runtime based on the order type, keeping carrier logic isolated from the controller layer.Request flow
A typical authenticated request travels through four layers:- Browser / frontend — The React app sends an HTTP request with an
Authorization: Bearer <token>header tohttp://localhost:8080/api/<service>/.... - api-gateway (port 8080) —
GatewayConfigmatches the path. For protected routes,AuthFilterintercepts the request, validates the JWT, and appendsX-User-Emailwith the subject claim. The/apiprefix is stripped viastripPrefix(1)before the request is forwarded. - Downstream service — The service receives the request on its own port (8082, 8083, or 8084) and processes it against its own PostgreSQL database. No service accesses another service’s database directly.
- Response — The downstream service responds through the gateway, which returns the response to the client.
JWT authentication
The gateway andauth-service share a single HMAC-SHA secret configured via the JWT_SECRET environment variable. The flow is:
- The client POSTs credentials to
/api/auth/login. This route is explicitly public inGatewayConfig— it proxies directly toauth-service:8081with noauthFilterapplied. auth-serviceverifies the credentials, signs a JWT with the user’s email as the subject, and returns it. Tokens expire after 86,400,000 ms (24 hours).- The client includes the token in the
Authorization: Bearerheader on all subsequent requests. AuthFilterinapi-gatewayparses and verifies the token using the shared secret. Valid tokens cause the filter to addX-User-Email: <subject>to the forwarded request. Invalid or missing tokens receive a401 Unauthorizedresponse immediately at the gateway.
X-User-Email to identify the caller without performing their own token verification.
Design patterns
Circuit breaker (Resilience4j)
ms-pedidos calls ms-inventario over HTTP to check stock before confirming an order. A Resilience4j circuit breaker wraps this call:
| Parameter | Value |
|---|---|
| Sliding window size | 10 requests |
| Failure rate threshold | 50% |
| Wait duration in open state | 30 seconds |
| Permitted calls in half-open state | 3 |
ms-inventario has recovered before the circuit closes again.
Factory Method
Bothms-pedidos and ms-envios use the Factory Method pattern to decouple object creation from business logic:
- ms-pedidos creates order handlers for
NACIONALandINTERNACIONALorder types. - ms-envios creates shipment handlers for
TERRESTRE(ground) andEXPRESScarrier types.
Observer (Spring ApplicationEvent)
Withinms-pedidos, the OrderService publishes a PedidoAprobadoEvent (a Spring ApplicationEvent) immediately after saving a new order. An internal NotificationListener in the same JVM handles this event asynchronously (@Async), logging the notification payload. The standalone notification-service is a separate REST listener on port 8085 that can receive arbitrary JSON payloads from any SmartLogix service. This design keeps notification logic decoupled from order processing without requiring an external message broker.
Database-per-service
Each service owns its own PostgreSQL database and schema.
auth-service connects exclusively to auth_db, ms-inventario to inventario_db, ms-pedidos to pedidos_db, and ms-envios to envios_db. There are no cross-service foreign keys at the database level. Referential integrity across service boundaries is maintained at the application layer — for example, ms-pedidos holds a productoId field that refers to an inventory record, but the two databases have no direct relationship. This boundary is what allows each service to be deployed, scaled, and migrated independently.Inter-service communication
Services call each other synchronously over HTTP using Spring’sRestTemplate. The service URLs are resolved using Docker Compose service names on the smartlogix-net bridge network:
ms-pedidos → ms-inventario path.