AthlEAT
Architecture

Architecture

Service architecture, components, and data flow


Overview

This page describes the internal architecture of the athlete-nutrition-ai service — the components that handle your requests, how they interact, and the decisions that shaped the system. Understanding this architecture helps you predict API behavior, design resilient integrations, and debug issues when something goes wrong. Whether you're building a client app, setting up webhooks, or troubleshooting latency, knowing how data flows through the system will make you a more effective consumer of this API.


Architecture diagram
Loading diagram...

Components

API Gateway Type: Ingress / Proxy Every HTTP request you send hits the API Gateway first. It is responsible for TLS termination, JWT validation (by delegating to the Auth Service), rate limiting, and routing to the correct downstream service. This single entry point means your integration always targets one base URL regardless of how the backend is structured.


Auth Service Type: Identity & Access Management Issues JWTs on successful sign-in and validates tokens on every subsequent request. It enforces token expiry and scope checks, so requests with missing or expired tokens are rejected here before reaching any business logic. You interact with this service explicitly only during account creation and sign-in; all other calls pass your token through the Gateway transparently.


Athlete Profile Service Type: Domain Service Stores and retrieves the structured data that makes nutrition advice personalized — dietary preferences, restrictions, sport type, body metrics, and performance goals. The AI Advisor depends heavily on this data, so keeping your athlete profiles accurate directly affects the quality of generated meal plans.


Training Calendar Connector Type: Integration Service Manages the link between athlete-nutrition-ai and external calendar providers (Google Calendar, iCal feeds, and similar). When you connect a calendar, this service registers the connection and schedules periodic sync jobs via the async queue. It normalizes heterogeneous event formats into a unified training-event schema that downstream services consume.


AI Nutrition Advisor Type: LLM Orchestration Service The core intelligence of the platform. When you open a chat session or request a meal plan, this service fetches the athlete's profile and upcoming training events, retrieves relevant nutritional knowledge from the Vector Store, and calls a large language model to produce a response. Short chat turns are handled synchronously; full meal-plan generation is dispatched as an async job to avoid request timeouts.


Shopping List Service Type: Domain Service Aggregates ingredients across a generated meal plan, deduplicates quantities, and formats the result into a structured list your application can render or export. It reads meal plans from the Primary Data Store, so a list is only available after the AI Advisor has committed a plan.


Subscription Service Type: Billing & Entitlement Service Enforces plan limits — for example, the number of meal plans generated per month or access to premium features. It syncs state with your billing provider via webhooks. API calls that exceed plan limits return a 402 Payment Required or 403 Forbidden response with a machine-readable reason code so your application can handle upgrade flows gracefully.


Primary Data Store Type: Persistent Storage A relational database that is the system of record for user accounts, athlete profiles, training events, meal plans, and shopping lists. All services that need durable reads or writes go through this store.


Vector Store Type: Semantic Search Index Holds embeddings of curated nutritional knowledge — food composition data, sports-nutrition guidelines, and dietary research. The AI Advisor queries this store with semantic search to ground its responses in factual nutrition data, reducing hallucination risk.


Async Event Queue Type: Message Broker Decouples long-running or externally dependent operations from synchronous API responses. Calendar syncs, AI meal-plan generation jobs, and billing webhook retries all flow through this queue. When your request triggers an async job, the API returns a 202 Accepted with a job ID you can poll for status.


Data flow

The following trace walks through one of the most common and data-intensive workflows: an athlete connects a training calendar and then asks the AI advisor to generate a weekly meal plan.

Step 1 — Authentication You call POST /auth/signin with credentials. The API Gateway forwards this to the Auth Service, which validates the credentials against the Primary Data Store and returns a signed JWT. All subsequent requests include this token in the Authorization: Bearer header.

Step 2 — Athlete Profile Setup You call POST /athletes or PUT /athletes/{id} to record dietary preferences, sport type, and goals. The API Gateway validates your JWT, confirms your subscription entitlements via the Subscription Service, and routes the request to the Athlete Profile Service, which persists the data in the Primary Data Store.

Step 3 — Calendar Connection You call POST /calendars with the calendar URL or OAuth token for the external provider. The Training Calendar Connector stores the connection metadata in the Primary Data Store and enqueues an initial sync job. The API returns 202 Accepted with a sync_job_id.

Asynchronously, the queue worker pulls the job, fetches events from the external calendar provider, normalizes them into the internal training-event schema, and writes them to the Primary Data Store. You poll GET /calendars/{id}/sync-jobs/{sync_job_id} to check completion status.

Step 4 — Reviewing Upcoming Events You call GET /athletes/{id}/events?from=<date>&to=<date>. The Athlete Profile Service reads upcoming training events from the Primary Data Store and returns a structured list. You can use this response to confirm the calendar sync succeeded before generating a meal plan.

Step 5 — AI Meal Plan Generation You call POST /athletes/{id}/meal-plans with your desired date range. The AI Nutrition Advisor:

  1. Reads the athlete's profile from the Primary Data Store.
  2. Reads upcoming training events for the requested period.
  3. Runs a semantic search against the Vector Store to retrieve relevant nutritional guidance.
  4. Dispatches a generation job to the Async Event Queue to avoid HTTP timeout on complex plans.
  5. Returns 202 Accepted with a plan_job_id.

The queue worker calls the LLM with a structured prompt containing profile data, event schedule, and retrieved nutrition context. The completed meal plan is written back to the Primary Data Store.

You poll GET /athletes/{id}/meal-plans/{plan_job_id}/status until the status is completed, then fetch the result at GET /athletes/{id}/meal-plans/{plan_job_id}.

Step 6 — Shopping List Generation You call POST /athletes/{id}/shopping-lists referencing the completed meal plan. The Shopping List Service reads the plan from the Primary Data Store, aggregates and deduplicates ingredients, and returns the structured list synchronously. No async job is needed here because this is a deterministic transformation of already-stored data.

Throughout — Subscription Enforcement At every service boundary, the Subscription Service is consulted to confirm the requested operation is within your plan's limits. If you exceed a limit, the service returns an error before any expensive downstream work begins.


Design decisions

Async processing for AI and calendar operations Meal-plan generation and external calendar syncs involve variable, sometimes lengthy execution times — LLM calls can take several seconds, and external calendar APIs may be slow or temporarily unavailable. Rather than holding HTTP connections open and risking client timeouts, the system immediately returns 202 Accepted with a job ID and processes these operations asynchronously. The trade-off is that your client must implement polling (or listen for a webhook, if supported), but this approach provides a far more reliable integration surface than a long-lived synchronous call.

Centralized API Gateway for auth and rate limiting Placing authentication validation and rate limiting at the gateway — rather than in each service — means you only need to manage one credential scheme and one set of rate-limit headers. It also means a misconfigured downstream service cannot accidentally skip auth checks. The cost is a small added latency on every request for the token validation round-trip.

Vector Store for nutrition knowledge grounding Instead of relying solely on the LLM's training data (which may be outdated or hallucinated), relevant nutritional facts are retrieved from a curated, indexed Vector Store at query time. This retrieval-augmented generation (RAG) pattern improves factual accuracy and allows the knowledge base to be updated independently of the model. The trade-off is additional query latency on each AI call and the operational complexity of maintaining the index.

Relational primary store as system of record A relational database was chosen for the Primary Data Store because the core domain entities — users, profiles, events, meal plans — have well-defined, stable relationships. Relational constraints enforce data integrity across services. The trade-off versus a document store is a more rigid schema, but for a nutrition-planning domain where correctness matters, that rigidity is a feature.

Subscription enforcement at the service layer, not the gateway Entitlement checks are delegated to the Subscription Service rather than implemented as gateway routing rules, because plan limits are business-logic decisions that can change frequently (e.g., a new plan tier). Centralizing this logic in a dedicated service makes it easy to update limits without touching the gateway configuration. The trade-off is that some requests travel further into the system before being rejected, but this is acceptable because limit checks are fast in-process reads from the data store.


Trade-offs

Polling vs. webhooks for async jobs Currently, long-running operations (meal plan generation, calendar sync) require your application to poll a status endpoint. Polling adds client complexity and can produce unnecessary API traffic if your polling interval is too short. If your architecture supports receiving inbound HTTP requests, a webhook-based notification model would be more efficient. Evaluate whether the polling model fits your integration before building; if not, check the API changelog or contact support for webhook availability.

LLM accuracy and determinism The AI Nutrition Advisor is a language model and is therefore non-deterministic — two identical requests may return different meal plans. The Vector Store grounding mitigates hallucination risk but does not eliminate it. If your use case requires reproducible, auditable output (for example, clinical dietary management), this service is not the right tool without additional human review in your workflow.

External calendar dependency The Training Calendar Connector relies on third-party calendar providers being available and returning well-formed data. If an external provider is down or changes its event format, syncs will fail or produce incomplete data. Your application should treat calendar-derived training events as eventually consistent rather than guaranteed to be current at any given moment. Design your UI and downstream logic accordingly.

Subscription enforcement granularity Plan limits are enforced at the service level but are not real-time transactional locks. Under high concurrency it is theoretically possible for usage to slightly exceed a plan limit before enforcement catches up. If precise hard limits are critical to your billing or compliance requirements, implement secondary checks on your side.

Single-region default The architecture as described does not specify multi-region deployment. If your users are geographically distributed and latency is a critical concern, confirm the available deployment regions with the platform team. A latency-sensitive integration (for example, a real-time coaching app) may need to account for geographic distance to the nearest service endpoint.