This document summarizes the technical architecture for the flashcard learning system. It focuses on the deployed components, their responsibilities, and the primary data and control flows.
Source of truth for this document: infra/docker-compose.yml (local dev), infra/docker-compose.azure.yml (deployed), and the per-service OpenAPI specs in api/.
| Layer | Technology | Notes |
|---|---|---|
| Client | TypeScript (React, Vite) | Browser UI for upload, decks, study, and explanations |
| API Gateway | Java (Spring Boot / Spring Cloud Gateway) | Single entry point behind the reverse proxy; routes and enforces JWT auth |
| Backend services | Java (Spring Boot) | auth-service, flashcard-service, study-service |
| GenAI service | Python (FastAPI) | Flashcard generation and explanation endpoints; RAG over uploaded documents |
| Upload service | Python (FastAPI) | Document upload/storage and metadata |
| Relational Database | PostgreSQL 16 | One database per service: authdb, flashcarddb, studydb, uploaddocumentdb, all on a shared db container |
| Vector Database | Weaviate | RAG retrieval for GenAI service, using Ollama's text2vec-ollama module |
| LLM Runtime | Ollama (local) + Logos (remote, TUM-hosted) | GenAI service can target either via LLM_BASE_URL/LOGOS_BASE_URL |
| Cache / Queue | Redis | Used by GenAI service |
| API contracts | OpenAPI | One spec per service in api/: auth.yaml, flashcard.yaml, study.yaml, upload.yaml, genAI.yaml |
| Reverse Proxy | Traefik | TLS termination (Let's Encrypt) and routing, deployed environment only |
| Observability | Prometheus, Grafana, Loki/Promtail, Jaeger | Metrics, dashboards, logs, and distributed tracing |
| Containerization | Docker / Docker Compose | Local development (infra/docker-compose.yml) and Azure deployment (infra/docker-compose.azure.yml) |
The system is a web client, an API gateway, three Java backend services, and two Python AI/document services, plus shared infrastructure (Postgres, Weaviate, Ollama, Redis) and an observability stack.
| Component | Owns | Talks to |
|---|---|---|
| Web Client | UI state and user interactions | API Gateway (REST, via generated SDK) |
| API Gateway | Routing, JWT validation, CORS | auth-service, flashcard-service, study-service, genai-service, upload-service |
| Auth Service | Users, sessions, JWT issuance, Google OAuth2 login | authdb |
| Flashcard Service | Individual flashcard CRUD | flashcarddb |
| Study Service | Decks, deck-flashcard associations, spaced-repetition study state | studydb |
| GenAI Service | Stateless flashcard generation and explanation (RAG) | Weaviate, Ollama, Logos (external LLM), Redis, upload-service |
| Upload Service | Uploaded document storage and metadata | uploaddocumentdb |
Note: decks live in study-service (/api/v1/decks), while individual flashcards are owned by flashcard-service (/api/v1/flashcards) — there is no separate "Deck Service".
- Each backend service owns its own PostgreSQL database (
authdb,flashcarddb,studydb,uploaddocumentdb), all hosted on one shareddbPostgres instance with per-database isolation. - Weaviate stores vector embeddings for RAG-based flashcard generation and explanations, using Ollama for embedding via the
text2vec-ollamamodule. - Redis backs the GenAI service (caching/session state).
- Uploaded documents are persisted by the
upload-serviceand referenced byuploaddocumentdb.
- External API boundary is REST/JSON, fronted by the API gateway at
/api/v1/.... - Each service has its own OpenAPI spec in api/ (no single merged
openapi.yaml):auth.yaml,flashcard.yaml,study.yaml,upload.yaml,genAI.yaml(JSON equivalents also present foruploadandgenAI). - These specs are the source of truth for endpoints and payloads; see api/README.md and api/scripts/gen-all.sh for client/stub generation.
This section summarizes the deployed services, their container ports, and the HTTP base paths they expose. In the Azure deployment, all backend services are only reachable internally (expose, not ports); the reverse proxy and gateway are the public entry points. Locally, all ports are published to the host for direct debugging.
| Service | Container Port | Local Host Port | Base Path | Notes |
|---|---|---|---|---|
| Web Client | 5173 (dev) / 80 (prod) | 5173 | / |
Vite dev server locally; static build behind Traefik in prod |
| API Gateway | 8080 | 8088 | /api, /oauth2, /login/oauth2 |
Single entry point for all backend calls |
| Auth Service | 8081 | 8081 | /api/v1/auth |
Login, register, refresh, logout, session/me, Google OAuth2 |
| Flashcard Service | 8082 | 8082 | /api/v1/flashcards |
Flashcard CRUD |
| Study Service | 8083 | 8083 | /api/v1/decks |
Decks, deck flashcards, study scheduling |
| GenAI Service | 8090 | 8090 | /api/v1/genai |
Uploads-to-flashcards generation, explain |
| Upload Service | 8091 | 8091 | /api/v1/documents |
Document upload, health, retrieval |
| Weaviate | 8080 / 50051 | 8080 / 50051 | — | Vector DB, internal only in prod |
| Ollama | 11434 | 11434 | — | Local LLM runtime, internal only in prod |
| Redis | 6379 | 6379 | — | GenAI cache, internal only in prod |
| Postgres | 5432 | 5432 | — | Shared instance, one DB per service |
| Reverse Proxy (Traefik) | 80/443 | — | / |
Deployed environment only; TLS + routing to gateway/web-client/monitoring |
| Prometheus | 9090 | 9090 | — | Metrics |
| Grafana | 3000 | 3001 | — | Dashboards |
| Loki | 3100 | 3100 | — | Log aggregation |
| Jaeger | 16686 / 4317 / 4318 | 16686 / 4317 / 4318 | — | Distributed tracing (OTLP) |
These diagrams capture the user interactions, domain model, and component-level architecture. They may not reflect the current service split described above and should be refreshed alongside this document.
- Use Case Diagram: documents/diagrams/Use Case Diagram.json
- Analysis Object Model: documents/diagrams/Analysis Object Model.json
- Component Diagram: documents/diagrams/Component Diagram.json
- User logs in via the web client;
auth-serviceissues a JWT (or handles Google OAuth2 login), validated independently by each downstream service. - User uploads material in the web client, routed through the API gateway to
upload-service, which stores the document and metadata. - The web client requests flashcard generation from
genai-service, which retrieves the uploaded document (viaupload-service), runs RAG over Weaviate/Ollama (or the remote Logos LLM), and returns generated flashcards. - Generated flashcards are persisted via
flashcard-service, and organized into decks viastudy-service. - Study sessions are driven by
study-service, which tracks per-flashcard study status and schedules reviews (spaced-repetition parameters configurable viaSTUDY_EASE_*env vars). - Users can request AI explanations, produced by
genai-serviceand returned through the gateway.
The genai-service (Python/LangChain) talks to LLMs through an OpenAI-compatible
/v1/chat/completions interface, with two backends:
- Logos API (default) — TUM-hosted, using the
openai/gpt-oss-120bmodel (LOGOS_BASE_URL,LOGOS_MODEL,LOGOS_API_KEY). - Ollama (local fallback) — a self-hosted
ollamacontainer running theqwen3:0.6bmodel (LLM_BASE_URL,LLM_MODEL). Qwen3 0.6B was chosen because of the memory constraints on the Azure VM and the Kubernetes cluster; it's small enough to run on CPU without the pod/VM getting OOM-killed.
At request time, llm_factory.py calls Logos first and only falls back to the
local Ollama model if the Logos call fails (e.g. missing/invalid LOGOS_API_KEY
or the API being unreachable).
Ollama also serves as the embedding provider for the Weaviate vector database
(used for RAG over uploaded flashcard documents): both the genai-service
(vector_store.py) and Weaviate's text2vec-ollama module use the
nomic-embed-text model, served from the same ollama container
(OLLAMA_API_ENDPOINT).