Week 1: Project Setup and Backend Foundations — A Production-Style FastAPI Stack with a Learning Layer
Introduction
Most “week 1” backend projects stop at scaffolding, a couple endpoints, and a todo list. This one is more interesting: it turns the first week of curriculum into a single Docker-run system with clear boundaries, real persistence, caching, and an engineer-facing dashboard—without spawning seven separate apps.
You’ll walk away with a concrete blueprint for structuring a FastAPI service as product workflows plus a learning layer, backed by PostgreSQL + Redis + MongoDB, and operated through a single docker compose up.
System overview
This project is a unified AI quiz platform with two API surfaces:
Product layer (
/api/v1): real workflows engineers ship—JWT auth, quiz CRUD, business rules, and session lifecycle.Learning layer (
/learn/lesson-0N): lesson-shaped endpoints that expose the curriculum as structured routes inside the same runtime.
Under the API sits a small composition core (core/) that owns domain rules, data access boundaries, and orchestration. The week’s topics show up as live modules: requirements and structure become predictable routes and tooling, architecture design becomes layering and dependencies, schema design becomes durable storage, and the “locked” lessons become full auth/quiz/session behaviors behind the product API.
Architecture Diagram
Engine / core system design
The core idea is to keep dependencies one-way:
backend/app/...(FastAPI routers) depend on…core/...(composition + domain services) which depends on…database clients (Postgres/Redis/Mongo) and DTOs
This makes it possible to keep /learn/... and /api/v1/... as separate route trees while sharing the same execution engine.
The engine-style composition is not a “framework inside a framework”. It’s a disciplined set of services with explicit wiring at the API edge.
That one constructor boundary is where “system architecture design” becomes real: you can swap caching strategies, add observability, or enforce business rules without touching routers.
Data Flow Diagram
API design
The API surface is small on purpose: a few endpoints that represent end-to-end behavior and keep the rest internal.
1) Register
POST /api/v1/auth/register
Request: { "username": "string", "email": "string", "password": "string" }
Response: { "message": "string", "user": { "id": "string", "username": "string", "email": "string" } }
Role: creates an account in MongoDB and prepares the user for JWT flows.
2) Login
POST /api/v1/auth/login
Request: { "username": "string", "password": "string" }
Response: { "access_token": "string", "token_type": "bearer", "expires_in": 1800 }
Role: issues a JWT and establishes identity for product workflows.
3) Create a quiz
POST /api/v1/quizzes/
Request: { "title": "string", "category": "string", "difficulty": "string", "questions": [ ... ] }
Response: { "id": 1, "title": "string", "is_published": false, "questions": [ ... ] }
Role: persists quiz data in Postgres and uses Redis for query caching.
4) Start and complete a session
POST /api/v1/sessions/
Request: { "quiz_id": "1" }
Response: { "id": "uuid", "user_id": "string", "quiz_id": "string", "status": "started", "version": 1 }
Role: creates an attempt row (Postgres) and a cached session record (Redis).
POST /api/v1/sessions/{session_id}/complete
Request: {}
Response: { "message": "Session completed", "session_id": "uuid" }
Role: flips attempt status to completed and drives “Completed attempts” metrics.
The delegation pattern is straightforward: routers authenticate, parse DTOs, then call core services.
State Machine Diagram
Why this architecture holds up
This structure scales because it makes the composition boundary explicit:
Adding new product features becomes adding new core services and thin routers.
Adding new lesson routes becomes adding new learning modules that call the same core, without contaminating product code paths.
The persistence split (Mongo for identity, Postgres for quiz/sessions, Redis for cache) is a deliberate trade-off: you gain operational clarity and speed, but you accept cross-store consistency work. In this project, that shows up most clearly around user identity: the quiz tables store
creator_idas a string, and you rely on JWT identity rather than foreign keys into MongoDB.
Conclusion
Week 1 becomes meaningful when scaffolding turns into a system you can operate: one runtime, one compose stack, and clear boundaries between learning routes and production workflows. This project’s core shows how to keep FastAPI thin, core services testable, and persistence intentional.
Next step: add one more product workflow (e.g., scoring on completion) and surface it as both a product endpoint and a lesson route—without changing the engine’s dependency direction.