FitTrack: Distributed Microservices Platform & Asynchronous AI Engine
An end-to-end fitness tracking ecosystem built with Java 21, Spring Boot 3, Spring Cloud Gateway, Eureka, RabbitMQ event queues, Keycloak PKCE authentication, polyglot persistence (PostgreSQL + MongoDB Atlas), and Google Gemini LLM integration.
Why Microservices for Fitness Telemetry & AI Processing?
In traditional monolithic fitness architectures, high-throughput activity ingestion (e.g., GPS points, cadence, heart rate, calories) shares resources with user identity management and heavy computational workloads like AI-based workout recommendations. This introduces severe systemic vulnerabilities:
- Synchronous Blocking by LLMs: Calling a Large Language Model (e.g. Gemini) can take anywhere from 1.5 to 4 seconds. Forcing mobile or web clients to wait synchronously stalls HTTP worker threads and degrades user responsiveness.
- Schema Rigidity vs. Dynamic Telemetry: Storing user authentication tables alongside polymorphic workout metrics (running pace vs. weightlifting sets/reps) in a single relational schema forces sparse columns or anti-pattern JSON blobs.
- Tight Coupling & Single Points of Failure: If the recommendation engine crashes under heavy load, the core user login and activity logging endpoints should remain unaffected.
FitTrack tackles this challenge with a distributed, event-driven microservices architecture: services have isolated data stores, communicate asynchronously via RabbitMQ, discover each other dynamically with Netflix Eureka, and route through a reactive Spring Cloud Gateway with Keycloak identity management.
Six Autonomous Backend Services & React Frontend
Every backend service is an independent Spring Boot application with its own database and configuration profile. Configuration is pulled at startup from a central Config Server, and service instances register with Eureka for dynamic discovery.
Centralized configuration authority. Downstream services pull their environment configuration (DB URLs, credentials, Eureka URIs) at boot time via spring.config.import.
Service registry providing heartbeat monitoring and client-side load balancing via lb://SERVICE-NAME. Enables services to discover each other without static IP addresses.
Reactive reverse proxy (WebFlux). Validates Keycloak JWTs against JWKS certificates, injects security headers, and routes requests to /api/users, /api/activities, and /api/recommendations.
User management and identity mapping. Backed by PostgreSQL (Supabase) via Spring Data JPA. Exposes validation endpoints consumed by Activity Service before activity persistence.
Workout tracking engine backed by MongoDB Atlas. Validates users via WebClient, saves polymorphic activity documents, and acts as RabbitMQ producer to broadcast workout events.
Asynchronous RabbitMQ consumer listening to activity.queue. Queries Google Gemini REST API, generates structured recovery insights, and writes recommendations to MongoDB.
┌──────────────────────────────────────────────┐
│ React 19 + Vite Frontend │
│ (Port 5173 · MUI v9 · Redux Toolkit) │
└───────────────────────┬──────────────────────┘
│ HTTP (Bearer JWT + X-User-ID)
▼
┌──────────────────────────────────────────────┐
│ Spring Cloud Gateway │
│ (Port 8080 · Reactive WebFlux) │
└───────────────┬──────────────────────┬───────┘
│ │
┌─────────────────────────┴─────────┐ │
▼ ▼ ▼
┌──────────────────────┐ ┌──────────────────────────┐
│ User Service │<──WebClient─┤ Activity Service │
│ (Port 8081·Postgres) │ (Validation)│ (Port 8082·MongoDB Atlas)│
└──────────────────────┘ └─────────────┬────────────┘
│
│ AMQP: fitness.exchange / activity.tracking
▼
┌──────────────────────────┐
│ RabbitMQ Event Broker │
│ (Port 5672·activity.queue)
└─────────────┬────────────┘
│
│ Async Consume
▼
┌──────────────────────────┐
│ AI Recommendation Service│
│(Port 8083·MongoDB Atlas) │
└─────────────┬────────────┘
│
│ HTTPS (Prompt / JSON Generation)
▼
┌──────────────────────────┐
│ Google Gemini API │
└──────────────────────────┘From Workout Submission to AI Insights
User signs in through Keycloak (port 8181). Frontend performs authorization code exchange with PKCE verification and extracts sub claim as X-User-ID.
React client submits POST /api/activities with Bearer JWT. Gateway verifies JWT validity against Keycloak’s JWKS endpoint (/protocol/openid-connect/certs) before proxying to Activity Service.
Activity Service validates that the user exists by executing a non-blocking GET /api/users/{userId}/validate call to User Service via Spring WebClient.
Activity is saved into MongoDB Atlas. The endpoint returns 201 Created to the client in under 50ms, without blocking on AI generation.
Activity Service publishes message to fitness.exchange with routing key activity.tracking. AI Service consumes message from activity.queue, formats contextual prompt, invokes Google Gemini, and persists structured recommendation in MongoDB.
Architecture Trade-offs & Polyglot Persistence
Asynchronous RabbitMQ vs. Synchronous REST
Calling LLM APIs involves latency spikes and potential rate limiting. Offloading AI recommendation generation to an AMQP message queue decouples user-facing activity logging latency from external API response times and ensures reliable message redelivery.
Polyglot Persistence: PostgreSQL + MongoDB
Relational PostgreSQL (Supabase) handles User identities, unique email constraints, and roles where ACID guarantees are essential. MongoDB Atlas handles fitness activities and AI recommendations, accommodating flexible additionalMetrics maps (pace, cadence, reps) across 8 distinct workout types.
OAuth2 Authorization Code with PKCE
Standard authorization code grant requires a client secret, which cannot be securely stored in single-page applications. Implementing PKCE (Proof Key for Code Exchange) cryptographically verifies that the code exchange request originates from the same browser instance that initiated login.
Centralized Configuration Management
Instead of managing isolated application.yml files across six microservices, the Spring Cloud Config Server provides single-point versioning for database credentials, RabbitMQ hosts, and JWT verification endpoints.
Verified Endpoints & AI Output Structure
The system supports full CRUD operations across user profiles, activities, and recommendations:
Activity types: RUNNING, WALKING, CYCLING, WEIGHT_TRAINING, YOGA, CARDIO, STRETCHING, OTHER.
Analysis: Performance evaluation based on pace, heart rate, and duration.Improvements: Actionable suggestions for recovery and training volume.Suggestions: Recommended next session focus.Safety: Injury prevention and hydration alerts based on max metrics.
Operational Complexities & Production Considerations
Operating a multi-service distributed suite presents distinct challenges that are honestly documented in the repository:
Services must be booted in strict sequence: Config Server (8888) → Eureka (8761) → Gateway (8080) → User Service (8081) → Activity Service (8082) → AI Service (8083). In a production cloud setting, Kubernetes readiness probes or container orchestrators would manage health gating automatically.
Because AI recommendations are processed asynchronously, navigating immediately to an activity detail page displays a placeholder until the Gemini response is generated and persisted. The frontend polls or expects 404 until generation concludes.
The current RabbitMQ configuration does not include an explicit Dead-Letter Exchange (DLX). If the Gemini API experiences sustained downtime or unparseable JSON responses, failed messages require manual retry rather than automated DLQ routing.
Running 6 Java virtual machines (JVMs) alongside Keycloak and RabbitMQ requires substantial memory overhead. The system is designed and tested as a local distributed testbed; deploying to production would benefit from GraalVM native image compilation to reduce RAM footprint.