Design โ Guarantees, Startup Pipeline, and the Contract Model
This page is the architecture reference: the fail-fast startup surface, the guarantees that hold by construction, and the trade-offs baked into every decision.
๐๏ธ 1. The Startup Pipeline
Everything happens once, eagerly, at construction time โ for the app at OpenAPIFirstApp(...), for the client at OpenAPIClient(...). There is no lazy loading, no deferred binding, no "it'll work on first request".
Client โ same spec, same guarantees:
๐ 2. Guarantees That Hold by Construction
These are not conventions โ they are enforced at startup or client construction:
- Every route is spec-declared. Routes are registered only from
paths; there is no decorator-driven or implicit routing. - Every operation is handled. Each
operationIdresolves to an exact handler name inroutes_module; a missing one aborts bootstrap. - Every operation has an
operationId. An operation without one cannot be bound and fails fast. - Client and server use the same spec. One document drives both sides, so they cannot drift.
- Auth is spec-driven.
securitydependencies come fromsecuritySchemes+ per-operationsecurity; no manual middleware. - Spec is valid before use. Invalid, malformed, or unloadable specs are rejected at load, not at first request.
The startup "no half-states" property
Because binding, validation, and security resolution all run at construction, a booted app is a provably-complete app. If the contract is violated in any way, the process refuses to start โ the failure is loud, immediate, and tells you exactly what to fix.
๐งฉ 3. Component Responsibilities
| Module | Owns | Refuses to |
|---|---|---|
loader |
parse + validate the spec | modify or "fix" the spec |
app |
assemble FastAPI from spec + handlers | routing decisions, decorators |
binder |
operationId โ handler mapping |
infer handlers from paths |
client |
build one callable per operationId |
guess URLs, deserialize implicitly |
security |
schemes โ FastAPI Depends |
manual middleware |
errors |
the error hierarchy | swallow failures |
codegen |
build-time model/routes generation | runtime codegen |
templates |
copyable scaffolds | production data stores |
Rule of thumb for contributors: keep modules coercive (they raise if the contract is wrong) and narrow (one responsibility each). Pydoclint + the test suite keep that contract honest.
โ๏ธ 4. Design Trade-offs (Accepted)
| Decision | Chosen because | What you give up |
|---|---|---|
| Handlers are plain callables | Framework-agnostic, testable, grep-able | No decorator sugar |
| Fail-fast at startup | Drift caught in CI, not at 3am | Slightly heavier boot |
Raw httpx.Response from client |
No hidden deserialization/validation | You read .json() yourself |
| Build-time codegen | One-way generation, no runtime generator dep | Spec must already be spec-valid |
| Templates copy verbatim | Scaffold, not magic | Templates never updated in place |