Microservices Topology Overview
tektree beginner 5 min read
ELI5
Tektree is a food court: each stall (service) cooks one thing — users, knowledge, gamification, payments, realtime, jobs — and a single host stand at the door (the gateway) checks IDs and walks every order to the right stall. The mall building itself is just the parking lot; each stall has its own lease (its own git repo).
Technical Deep Dive
The workspace at /home/devarno/code/workspace/tektree-io mirrors the tektree-io GitHub org. Every directory under services/, libs/, frontend/, infra/, docs/ is an independent git repo with its own go.mod/package.json and CI. The workspace root has no top-level Makefile or monorepo manifest — cd into the subrepo before running tooling.
C4 Context Diagram
---title: "TekTree System Context"---flowchart TD user(("<b>End User</b><br/>Web or mobile client")):::person subgraph tt ["**TekTree Platform**"] gw["<b>api-gateway :8080</b><br/>Public ingress, JWT, rate-limit, reverse proxy"]:::system svc["<b>Backend Services</b><br/>user, knowledge, gamification, payment, realtime"]:::system wp["<b>worker-pool</b><br/>Redis Streams job consumer"]:::system end mongo[("<b>MongoDB</b><br/>Primary datastore")]:::db redis[("<b>Redis</b><br/>Rate-limit + Streams bus")]:::db polar["<b>Polar.sh</b><br/>Subscription billing"]:::ext user -- "HTTPS / WebSocket" --> gw gw -- "HTTP, X-User-ID/X-User-Tier headers" --> svc svc -- "drivers" --> mongo svc -- "cache + event-bus" --> redis wp -- "XREADGROUP jobs" --> redis svc -- "checkout + webhooks" --> polar
classDef person fill:#1c1c24,stroke:#e85d3e,color:#f0ece6 classDef system fill:#1c1c24,stroke:#d4a574,color:#f0ece6 classDef ext fill:#141419,stroke:#8b7e74,color:#f0ece6,stroke-dasharray: 4 3 classDef db fill:#1c1c24,stroke:#d4a574,color:#f0ece6 classDef container fill:#1c1c24,stroke:#d4a574,color:#f0ece6Service Inventory
| Service | Port | Cmd | Role |
|---|---|---|---|
services/api-gateway | 8080 | cmd/server/main.go | Only public ingress; JWT auth; tier rate-limit; reverse-proxy |
services/user-service | 8081 | cmd/server/main.go | Identity / profile CRUD |
services/knowledge-service | 8082 | cmd/server/main.go | Areas, questions, insights, resources |
services/gamification-service | 8083 | cmd/server/main.go | XP, achievements, leaderboards |
services/payment-service | 8084 | cmd/server/main.go | Polar subscriptions + webhooks |
services/realtime-service | 8085 | cmd/server/main.go | WebSocket hub + Redis presence |
services/worker-pool | — | cmd/worker/main.go | Background jobs from Redis Stream jobs |
services/api (legacy) | 8000 | main.go | Pre-split monolith; 23 controllers; cookie auth |
Shared libs sit under libs/: shared-go (auth, config, logging, metrics, errors), event-bus (Redis Streams envelope + publisher/subscriber), proto (gRPC scaffolding — generated, not used between services today). Clients live under frontend/web (Next.js 14 App Router, pnpm) and frontend/mobile (Expo SDK 50).
Edit-scope Rule
Per the workspace CLAUDE.md, each subrepo is independent — build, test, and lint commands run per-subrepo. Scope a change to one subrepo at a time. Cross-cutting docs in docs/docs/architecture/ (ARCHITECTURE_OVERVIEW.md, EVENT_CATALOG.md, DATA_MODELS.md, SECURITY_ARCHITECTURE.md, OBSERVABILITY_PLAN.md) are the source of truth for cross-service decisions.
Key Terms
- Subrepo → an independent git repo nested in the workspace mirror; not a monorepo package.
- api-gateway → the only public ingress; downstream services are not directly exposed.
- Public ingress → port
:8080; everything else is internal-only by convention. - Worker-pool → headless service consuming Redis Stream
jobs; no HTTP surface.
Q&A
Q: Where do you regenerate gRPC code if you change libs/proto/user.proto?
A: From the libs/proto subrepo using its buf.gen.yaml / buf.yaml configuration. Generated Go is checked in; do not hand-edit it.
Q: Why is services/api listed but flagged “legacy”?
A: It is the pre-split monolithic Gin server (port 8000, 23 controllers under controllers/, models/, routes/ at the top level). Treat it as legacy unless a task explicitly targets it; new work belongs in the matching services/<name>-service subrepo.
Q: What enforces tier-based rate limits? A: Only the api-gateway. Downstream services trust the gateway and do not re-implement limits.
Examples
To add a new endpoint that lists a user’s earned achievements: edit services/gamification-service/internal/handlers/handlers.go and register the route in cmd/server/main.go; then add ANY /achievements/*path (or a more specific route group) to services/api-gateway/internal/routes/routes.go. Two subrepos touched, two CI runs.
neighbors on the map
- Choco Factory Architecture Map onboarding to a new choco service repo
- Two-Service Architecture onboarding to the chronicle-hq monorepo
- Multi-Strategy Authentication debugging 401 errors across different clients