Skip to content

3. Domain-Driven Design to Microservices

In the following chapter we describe how the domain model has been translated into a distributed architecture based on microservices, service discovery, and event-driven integration.

3.1 System Operations

This section shows the main operations identified in the SmartGym Monitor system. Operations are derived from the use cases and represent the commands exposed by the services.

ActorRelated Use CaseCommandDescription
Gym MemberAccess GymstartGymSession(badgeId)Creates a new gym session when the badge is validated at the entrance.
Gym MemberExit GymendGymSession(badgeId)Closes the active gym session and updates the global gym count.
Gym MemberAccess AreaprocessAreaAccess(message)Registers an access event for a specific area and increments area occupancy.
Gym MemberExit AreaprocessAreaExit(message)Registers an exit event for a specific area and decrements area occupancy.
Gym MemberUse MachinestartMachineSession(message)Starts a machine session and marks the machine as occupied.
Gym MemberStop Using MachineendMachineSession(message)Ends the active machine session and frees the machine.
AdminCreate MachinecreateMachine(message)Creates a machine and associates it with an area.
AdminUpdate MachineupdateMachine(machineId, message)Updates machine metadata and area association.
AdminSet MaintenancesetMachineMaintenance(message)Changes the machine state to maintenance.
AdminLoginhandleLogin(credentials)Validates admin credentials and issues a JWT token.

Table 3.1: Main System Operations

QueryDescription
getGymCount()Returns the total number of members currently inside the gym.
getActiveSessions()Returns the list of currently active gym sessions.
getAreaById(areaId)Returns the occupancy status and capacity of a specific area.
getAllAreas()Returns all configured gym areas.
getMachineStatus(machineId)Returns the current state of a machine.
getAllMachines()Returns all configured machines.
getMachineHistory(machineId)Returns historical usage sessions for a machine.
getMachineUsageSeries(from, to, granularity, areaId, machineId)Returns machine usage time series with optional filters.
getAllAttendanceStats()Returns all attendance statistics.
getAttendanceSeries(from, to, granularity, areaId)Returns attendance time series with optional filters.
getGymSessionDurationByDate(date)Returns gym session duration statistics for a specific date.
getAllDeviceStatuses()Returns the current status of all simulated devices.

Table 3.2: Main System Queries

3.2 Subdomains to Microservices

Each bounded context has been mapped to a dedicated microservice in order to preserve separation of concerns, service autonomy, and database isolation.

3.2.1 Tracking Service (Core)

The tracking-service implements the core domain of the system. It manages gym sessions and the global count of members currently inside the gym.

ResponsibilityDescription
Gym Session ManagementCreates and terminates GymSession entities when members enter or exit the gym.
Global Gym CountMaintains the real-time number of people inside the gym.
Invariant EnforcementEnsures that a badge cannot have more than one active session at the same time.
PersistenceStores session history in its own MongoDB database.

Table 3.3: Tracking service responsibilities

3.2.2 Area Management Service (Supporting)

The area-service manages gym areas and area-level occupancy.

ResponsibilityDescription
Area ConfigurationDefines and updates area metadata such as name and capacity.
Occupancy TrackingMaintains the current number of people inside each gym area.
Capacity EnforcementGuarantees that 0 ≤ currentCount ≤ capacity always holds.
Event HandlingProcesses access and exit messages coming from the embedded layer.

Table 3.4: Area service responsibilities

3.2.3 Machine Management Service (Supporting)

The machine-service manages machines, machine sessions, and state transitions.

ResponsibilityDescription
Machine ConfigurationManages machine metadata and association with areas.
Machine Session LifecycleCreates and closes MachineSession entities.
State Transition ValidationEnsures valid transitions between Free, Occupied, and Maintenance.
Consistency EnforcementGuarantees that a machine cannot have more than one active session simultaneously.

Table 3.5: Machine service responsibilities

3.2.4 Embedded Service (Supporting)

The embedded-service acts as the bridge between simulated devices and backend services. It is not a classic CRUD microservice: its main responsibility is to receive MQTT messages, translate them, and forward them to the operational services through HTTP adapters.

ResponsibilityDescription
Device IntegrationManages RFID readers, turnstiles, doors, and proximity sensors.
Message TranslationConverts low-level device messages into structured application messages.
Asynchronous CommunicationConsumes and publishes MQTT messages on the broker.
Forwarding LayerInvokes the tracking, area, machine, and analytics services through adapters.

Table 3.6: Embedded service responsibilities

3.2.5 Analytics Service (Generic)

The analytics-service provides historical and aggregated information for monitoring.

ResponsibilityDescription
Attendance StatisticsComputes gym attendance trends and peak hours.
Machine Usage AnalysisCalculates machine utilization rates and dwell time.
Historical Data AggregationProcesses domain events to generate analytical snapshots.
Read Model ManagementMaintains optimized read models for the dashboard.

Table 3.7: Analytics service responsibilities

3.2.6 Authentication Service (Generic)

The auth-service manages administrator authentication and token-based security.

ResponsibilityDescription
Admin AuthenticationValidates administrator credentials.
Token ManagementIssues JWT access tokens and supports token validation in the gateway.
Access ControlProtects dashboard access and service calls that require authorization.
User RegistryStores the seeded administrator account and login history.

Table 3.8: Authentication service responsibilities

3.2.7 Infrastructure Services

The architecture also includes two supporting infrastructure services:

  • service-discovery: Eureka registry used to register and discover services;
  • gateway: Spring Cloud Gateway entry point that routes requests to the registered services and enforces JWT checks on protected calls.

3.3 System Operation Identification

This section identifies the main operations exposed by each microservice and the components they collaborate with.

MicroserviceOperationsCollaborators
tracking-servicestartGymSession(), endGymSession(), getGymCount(), getActiveSessions()embedded-service, auth-service
area-serviceprocessAreaAccess(), processAreaExit(), getAreaById(), getAllAreas(), updateAreaCapacity()embedded-service, tracking-service
machine-servicecreateMachine(), updateMachine(), startMachineSession(), endMachineSession(), setMachineMaintenance(), getAllMachines(), getMachineStatus(), getMachineHistory(), getMachineUsageSeries()embedded-service, tracking-service, area-service
analytics-serviceingestEvent(), getAllAttendanceStats(), getAttendanceSeries(), getGymSessionDurationByDate()tracking-service, area-service, machine-service
auth-servicehandleLogin(), handleRegister(), handleVerifyUser(), handleLogout()gateway, frontend
embedded-serviceMQTT event handling, HTTP forwarding, getAllDeviceStatuses()tracking-service, area-service, machine-service, analytics-service

Table 3.9: Microservice operations and collaborators

3.4 API Interface Definition and Identification

The system exposes two integration layers: asynchronous MQTT communication for simulated devices and synchronous REST APIs for the backend microservices and the frontend.

3.4.1 Gateway and Service Discovery

The gateway is the external HTTP entry point of the backend. It uses Eureka to discover the registered services and applies JWT validation through a global filter.

Relevant behavior:

  • public access is allowed for actuator paths and authentication endpoints such as /login and /register;
  • protected requests must carry a Bearer token in the Authorization header;
  • after validation, the gateway injects X-User-Id into the forwarded request;
  • routes are resolved through service discovery (lb://...) rather than hard-coded hostnames.

The gateway routes the following service families:

  • auth-service
  • analytics-service
  • embedded-service
  • machine-service
  • area-service
  • tracking-service

3.4.2 Authentication Service

The authentication service exposes the following controller paths:

EndpointTypeDescription
/loginPOSTAuthenticates an administrator and returns a JWT token.
/registerPOSTRegisters a new user.
/login/{username}GETVerifies whether a user exists.
/logoutPOSTRegisters the logout event using the X-User-Id header.

Table 3.10: Authentication service endpoints

3.4.3 Tracking Service

The tracking service exposes the following controller paths:

EndpointTypeDescription
/start-sessionPOSTCreates a new gym session.
/end-sessionPOSTEnds the active gym session.
/countGETReturns the current gym count.
/active-sessionsGETReturns active gym sessions.

Table 3.11: Tracking service endpoints

3.4.4 Area Management Service

The area service exposes the following controller paths:

EndpointTypeDescription
/accessPOSTRegisters entry to a specific area.
/exitPOSTRegisters exit from a specific area.
/{areaId}GETReturns a specific area by id.
/GETReturns all areas.
/capacityPUTUpdates the maximum capacity of an area.

Table 3.12: Area service endpoints

3.4.5 Machine Management Service

The machine service exposes the following controller paths:

EndpointTypeDescription
/machinesPOSTCreates a new machine.
/machines/{machineId}PUTUpdates machine metadata.
/start-sessionPOSTStarts a machine session and marks the machine as occupied.
/end-sessionPOSTEnds the active machine session and frees the machine.
/set-maintenancePOSTSets the machine status to maintenance.
/machinesGETReturns all configured machines.
/{machineId}GETReturns the current state of a machine.
/history/{machineId}GETReturns the historical usage sessions of a machine.
/machines/history/seriesGETReturns machine usage time series with optional filters.

Table 3.13: Machine service endpoints

3.4.6 Analytics Service

The analytics service exposes the following controller paths:

EndpointTypeDescription
/events/ingestPOSTIngests a domain event into the analytics pipeline.
/attendanceGETReturns all attendance statistics.
/attendance/seriesGETReturns attendance time series with optional filters.
/gym-session-duration/{date}GETReturns gym session duration statistics for a specific date.

Table 3.14: Analytics service endpoints

3.4.7 Embedded Service and MQTT Topics

The embedded layer is primarily driven by MQTT rather than by business REST endpoints. The Go simulator publishes events to the broker using the following topics:

  • smartgym/gym-access
  • smartgym/area-access
  • smartgym/machine-usage
  • smartgym/device-status

The embedded service consumes these messages, normalizes their payloads, and forwards the resulting commands to the backend services through HTTP adapters.

In addition, it exposes a single REST endpoint:

EndpointTypeDescription
/statusesGETReturns the current status of all simulated devices.

Table 3.15: Embedded service endpoints

3.4.8 Frontend Flask Application

The frontend is a lightweight Flask application used as the administrative entry point. Its main routes are:

EndpointTypeDescription
/GETRedirects to the dashboard or login page depending on the session.
/loginGETRenders the login form.
/loginPOSTAuthenticates the administrator via auth-service.
/logoutGETClears the session and notifies the auth service.
/dashboardGETDisplays the user dashboard and service connectivity summary.
/liveGETRenders the live monitor page for real-time area occupancy.
/historyGETRenders the history page for historical data exploration.
/api/healthGETReturns a simple health response for deployment checks.
/api/statusesGETReturns device statuses from the embedded-service.
/api/analytics/dashboardGETReturns dashboard analytics (attendance and session duration).
/api/machinesGETReturns all machines from the machine-service.
/api/live-monitorGETReturns live area and machine occupancy data.
/api/maintenance/togglePOSTToggles machine maintenance status.
/api/history/filtersGETReturns available filter options (areas and machines) for history.
/api/historyGETReturns historical attendance and machine usage data.

Table 3.16: Frontend Flask routes

3.5 Architectural Notes

The design follows a database-per-service approach with independent MongoDB instances for the operational and analytical services. This reduces coupling and allows each bounded context to evolve separately.

The overall flow is:

  1. the simulator generates device events via MQTT;
  2. the embedded service translates them into application-level messages;
  3. the operational services update their local state;
  4. analytics stores and aggregates historical data;
  5. the frontend interacts with the auth service and displays the dashboard to administrators.