Skip to main content
SmartLogix is built as a set of independently deployable microservices, each owning its domain, its database, and its schema. All external traffic enters through a single Spring Cloud Gateway MVC instance (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

ServicePortRoleDatabase
api-gateway8080JWT validation, routing, header injection
auth-service8081User registration, login, token issuanceauth_db (PostgreSQL)
ms-inventario8082Product catalog and stock managementinventario_db (PostgreSQL)
ms-pedidos8083Order creation and lifecyclepedidos_db (PostgreSQL)
ms-envios8084Shipment tracking and carrier selectionenvios_db (PostgreSQL)
notification-service8085Receives and dispatches event notifications
frontend5173 (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:
  1. Browser / frontend — The React app sends an HTTP request with an Authorization: Bearer <token> header to http://localhost:8080/api/<service>/....
  2. api-gateway (port 8080)GatewayConfig matches the path. For protected routes, AuthFilter intercepts the request, validates the JWT, and appends X-User-Email with the subject claim. The /api prefix is stripped via stripPrefix(1) before the request is forwarded.
  3. 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.
  4. Response — The downstream service responds through the gateway, which returns the response to the client.

JWT authentication

The gateway and auth-service share a single HMAC-SHA secret configured via the JWT_SECRET environment variable. The flow is:
  1. The client POSTs credentials to /api/auth/login. This route is explicitly public in GatewayConfig — it proxies directly to auth-service:8081 with no authFilter applied.
  2. auth-service verifies 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).
  3. The client includes the token in the Authorization: Bearer header on all subsequent requests.
  4. AuthFilter in api-gateway parses and verifies the token using the shared secret. Valid tokens cause the filter to add X-User-Email: <subject> to the forwarded request. Invalid or missing tokens receive a 401 Unauthorized response immediately at the gateway.
Downstream services can read 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:
ParameterValue
Sliding window size10 requests
Failure rate threshold50%
Wait duration in open state30 seconds
Permitted calls in half-open state3
When the failure rate exceeds 50%, the circuit opens and subsequent calls fail fast with a fallback response for 30 seconds. After that, 3 probe calls determine whether ms-inventario has recovered before the circuit closes again.

Factory Method

Both ms-pedidos and ms-envios use the Factory Method pattern to decouple object creation from business logic:
  • ms-pedidos creates order handlers for NACIONAL and INTERNACIONAL order types.
  • ms-envios creates shipment handlers for TERRESTRE (ground) and EXPRESS carrier types.
Adding a new order type or carrier requires implementing a new concrete class — no changes to the calling code.

Observer (Spring ApplicationEvent)

Within ms-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’s RestTemplate. The service URLs are resolved using Docker Compose service names on the smartlogix-net bridge network:
# ms-pedidos application.properties
inventario.service.url=http://ms-inventario:8082
There is no service registry or load balancer between services in the current setup. Communication is point-to-point, with resilience provided by the Resilience4j circuit breaker on the ms-pedidosms-inventario path.