CTRL+STRUM // BUILDER LOG
Backend City: Day 01: Laying a Real API Foundation (FastAPI, Tooling, Structure)
Day 01 is not glamorous. There are no fireworks. No “look mom I built OAuth.” This is the day we pour concrete and put up scaffolding — so the city doesn’t turn into a haunted parking garage later.
Why Day 01 matters
In production systems, the “boring stuff” is what keeps your service alive: clean structure, predictable configuration, health checks for load balancers, and tooling so every run/test/format action is identical across machines.
The goal is simple: make future changes boring. Boring means repeatable. Repeatable means survivable.
What we built (the concrete pour)
- Project structure with clear separation (app/, tests/, docs/)
- Router-based FastAPI layout so endpoints scale without chaos
- Health endpoint: GET /api/v1/health returns {"status":"ok"}
- API versioning baked in via /api/v1
- Typed settings using pydantic-settings (env-first, .env for local)
- CORS configured for local dev frontends (Vite/Next/etc.)
- Lifespan startup logging (no deprecated on_event)
- .env.example so setup is obvious and reproducible
- Makefile runbook: run, run2, kill, test, fmt
- Ruff formatting/linting configured via pyproject.toml
- Pytest scaffolding with a first health-check test
- Auto-generated API docs: Swagger UI at /docs + schema at /openapi.json
The core ideas (Backend City translation)
1) Routers = districts
If everything lives in one file, your “city” becomes a junk drawer. Routers let you build districts: users, auth, billing, etc. Teams can own a district without stepping on each other.
2) Health checks = the city heartbeat
Load balancers, deploy pipelines, and orchestrators all ask one question: “Are you alive and ready?” That’s what /health answers. It starts simple — and later grows into readiness/liveness checks and dependency verification.
3) Settings = zoning laws for environments
Dev, staging, prod — same code, different rules. Typed config prevents “works on my machine” from becoming “outage in prod.” Env vars for production, .env for local, and validation at startup.
4) CORS = letting the right cars into the city
During development, your frontend is usually on a different port. Browsers will block requests unless you explicitly allow them. Local dev gets a wide allowlist. Production gets strict origins only.
5) Tooling = the foreman on the construction site
A Makefile isn’t “extra.” It’s how you make commands consistent: one way to run, one way to test, one way to format. When a team grows, this stops friction from becoming culture debt.
6) /docs = the city’s public map
Swagger UI is your “show me what this API actually does” page. It proves your routes are registered, your schemas are valid, and your versioning prefix is working — without anyone needing to read the code first.
How to run & test (the “don’t guess” section)
Format + lint
make fmtRun tests
make testRun server (default 8000)
make runRun server on another port
make run PORT=8002
# or
make run2 # runs 8001Kill whatever is holding your port hostage
make kill
# or
make kill PORT=8002Verify health
curl http://127.0.0.1:8000/api/v1/healthVerify docs + schema
open http://127.0.0.1:8000/docs
curl http://127.0.0.1:8000/openapi.jsonWhat tripped me up
FastAPI’s on_event startup pattern throws a deprecation warning now. Switching to lifespan handlers is the correct move — and it’s exactly why Day 01 exists: fix the foundation while it’s still cheap.
How this scales (real-world)
- Health checks grow into readiness/liveness and dependency status
- Routers become team-owned modules or split into services cleanly
- Settings become secrets-aware config pipelines (Vault/SSM/etc.)
- Tooling becomes CI gates (make test + make fmt)
- Tests become the permission slip for refactors
- API versioning prevents client breakage as the system evolves
- /docs becomes your living contract (and the fastest sanity check in the stack)
Next up
Day 01 is infrastructure. Day 02 is where we start enforcing rules: request schemas, validation, and the early “building codes” that keep APIs clean.
~ ben.tankersley ⌁ echo "foundation poured."
~ ben.tankersley ⌁> Last note sent by Ben Tankersley