Skip to main content

System architecture

Read this when you need a map of the running system before changing a service, a route, a frontend or the development environment.

This page describes the development environment on homelab-talos-dev, defined in k8s/dev/base/. Production is deployed from a private repository and is not documented here.

Components​

ComponentRoleDefined in
Tadoku APIServes every public HTTP operation and publishes typed jobs in the business transaction.services/tadoku-api/, k8s/dev/base/services/tadoku-api.yaml
Tadoku workerExecutes registered jobs and composes feature operations.services/tadoku-api/cmd/tadoku-worker/, k8s/dev/base/services/tadoku-worker.yaml
webv2Main site: logging, contests, leaderboards and contentfrontend/apps/webv2/, k8s/dev/base/frontend-webv2/
authv2Account app: login, registration, recovery and Settings through the identity APIfrontend/apps/authv2/, k8s/dev/base/frontend-authv2/
adminAdministration, moderation and CMSfrontend/apps/admin/, k8s/dev/base/frontend-admin/
Ory OathkeeperAccess proxy for API and operator routes; issues user and service JWTsk8s/dev/base/oathkeeper/
token-reflectorPublishes the Kubernetes service-account JWKS and returns exchanged service tokensservices/token-reflector/
FliptFeature flagsk8s/dev/base/flipt/, feature-flags.contract.json
PostgreSQLTadoku API database in an operator-managed serverk8s/dev/base/data/postgres.yaml
ValkeyCaches and throttling counters; PostgreSQL stays the source of truthk8s/dev/base/data/cache.yaml

Each component runs in its own tdk-dev-* namespace. tdk-dev-routing attaches the application routes to the platform Envoy Gateway.

Request paths​

browser → ingress-nginx → Envoy → webv2 / authv2 / admin
→ Oathkeeper → Envoy → Tadoku API
  • Browser API calls go to /api/internal/<domain>/… on the main host. Oathkeeper checks the native session cookie with Tadoku API or accepts an anonymous request, replaces it with a signed JWT (id_token mutator) and forwards to Tadoku API. Tadoku API verifies that JWT against Oathkeeper's JWKS and rejects banned users before any operation runs. See Authorization.
  • Service calls use short-lived service JWTs from the Oathkeeper token exchange. Tadoku API uses them to reach Flipt. See Service-to-service authentication.
  • Operator routes such as the Flipt UI on flags.tadoku.dev.lab require a native session, and Oathkeeper asks Tadoku API whether that user is an administrator.
  • Branch routing: Envoy sends each request to a developer's branch overlay when one is selected and healthy, and to the base otherwise. See Development environment.

Data​

  • Tadoku API owns the application schema. Its migrations live in services/tadoku-api/migrations/ and run as Argo CD sync hooks before the API starts.
  • PostgreSQL is the source of truth for leaderboards. Valkey holds sorted-set caches of the unfiltered leaderboards, each built from a board version that PostgreSQL triggers raise with every write. A read serves a cached board only when it was built from the current version, and rebuilds it otherwise, so a served board reflects every committed write. See Leaderboard freshness and worker health.
  • Filtered requests, cache misses and cache errors read a leaderboard from PostgreSQL; other requests read a page from Valkey. Contest boards and official boards, yearly and global, each have one statement in services/tadoku-api/sql/leaderboard/leaderboard.sql that decides who is on the board, with optional filters. It both rebuilds the cache and serves the PostgreSQL reads, so cached and filtered views list the same users.
  • A log counts on the official boards when its eligible_official_leaderboard is set. Every request that attaches or detaches a live user's log, including a registration that drops a language, recomputes that flag in the same transaction from whether an official contest is still attached. Nothing recomputes stored flags in bulk: a stored flag is corrected only when its log's attachments next change.
  • Both paths order a board by score descending, then user ID descending, so pages from either store line up: Valkey's sorted set does so for cached pages, and pageOf in services/tadoku-api/features/leaderboard/leaderboard_service.go for PostgreSQL rows. buildEntries in the same file assigns competition ranks and tie flags for both.
  • Administrator and ban relationships are tenant-owned rows in the Tadoku API database; see Authorization.
  • The former Keto database and namespace are retained without a service. Their removal requires a separate data-disposition decision; see Development base.

Where to go next​