The architecture of FastAPI, x-rayed
FastAPI is famously a thin, sharply-focused layer: almost everything network-facing is delegated to Starlette, and almost everything data-facing to Pydantic. The x-ray makes that visible — 48 components, and the heavy ones are exactly where the framework adds its own value: routing, dependency injection, and OpenAPI schema generation.
archsteer xray v0.4.1 against fastapi/fastapi@dd17e4f (fastapi/) on 2026-07-05. Read-only static analysis — no code executed, no architecture rules declared. Structure, not judgment.Module dependency graph
Top 14 modules by connectivity; an arrow means "imports from".
graph LR
m0["__init__"]
m1["_compat"]
m2["applications"]
m3["datastructures"]
m4["dependencies"]
m5["encoders"]
m6["exceptions"]
m7["openapi"]
m8["param_functions"]
m9["params"]
m10["routing"]
m11["security"]
m12["types"]
m13["utils"]
m0 --> m2
m0 --> m3
m0 --> m6
m0 --> m8
m0 --> m10
m1 --> m7
m1 --> m9
m1 --> m12
m2 --> m0
m2 --> m3
m2 --> m4
m2 --> m6
m2 --> m7
m2 --> m9
m2 --> m10
m2 --> m12
m2 --> m13
m3 --> m0
m3 --> m1
m4 --> m1
m4 --> m6
m4 --> m9
m4 --> m11
m4 --> m12
m4 --> m13
m5 --> m1
m5 --> m6
m5 --> m12
m6 --> m0
m7 --> m1
m7 --> m3
m7 --> m4
m7 --> m5
m7 --> m6
m7 --> m9
m7 --> m10
m7 --> m12
m7 --> m13
m8 --> m0
m8 --> m1
m8 --> m3
m8 --> m7
m8 --> m9
m8 --> m11
m9 --> m1
m9 --> m3
m9 --> m6
m9 --> m7
m10 --> m0
m10 --> m1
m10 --> m3
m10 --> m4
m10 --> m5
m10 --> m6
m10 --> m9
m10 --> m12
m10 --> m13
m11 --> m0
m11 --> m6
m11 --> m7
m11 --> m8
m13 --> m0
m13 --> m1
m13 --> m3
m13 --> m6
m13 --> m10Components by module
Most connected components
Top 20 of 48 by exported API surface and dependency count.
| Component | Module | Key exports |
|---|---|---|
routing.py | routing | request_response, websocket_session, _AsyncLiftContextManager, _wrap_gen_lifespan_context |
applications.py | applications | FastAPI |
dependencies/utils.py | dependencies | ensure_multipart_is_installed, get_parameterless_sub_dependant, get_flat_dependant, _get_flat_fields_from_params |
openapi/models.py | openapi | BaseModelWithConfig, Contact, License, Info |
_compat/v2.py | _compat | evaluate_forwardref, GenerateJsonSchema, asdict, ModelField |
openapi/utils.py | openapi | get_openapi_security_definitions, _get_openapi_operation_parameters, get_openapi_operation_request_body, generate_operation_id |
_compat/__init__.py | _compat | — |
_compat/shared.py | _compat | lenient_issubclass, _annotation_is_sequence, field_annotation_is_sequence, value_is_sequence |
security/http.py | security | HTTPBasicCredentials, HTTPAuthorizationCredentials, HTTPBase, HTTPBasic |
param_functions.py | param_functions | Path, Query, Header, Cookie |
encoders.py | encoders | isoformat, decimal_encoder, generate_encoders_by_class_tuples, jsonable_encoder |
params.py | params | ParamTypes, Param, Path, Query |
security/oauth2.py | security | OAuth2PasswordRequestForm, OAuth2PasswordRequestFormStrict, OAuth2, OAuth2PasswordBearer |
exceptions.py | exceptions | EndpointContext, HTTPException, WebSocketException, FastAPIError |
__init__.py | __init__ | — |
security/api_key.py | security | APIKeyBase, APIKeyQuery, APIKeyHeader, APIKeyCookie |
datastructures.py | datastructures | UploadFile, DefaultPlaceholder, Default |
utils.py | utils | is_body_allowed_for_status_code, get_path_param_names, create_model_field, generate_operation_id_for_path |
responses.py | responses | _UjsonModule, _OrjsonModule, UJSONResponse, ORJSONResponse |
security/__init__.py | security | — |
Declared runtime dependencies
What the structure teaches
Two files carry the framework
routing.py and applications.py are by far the most connected components — they export the APIRouter/FastAPI classes everyone touches and import from nearly every other module. This is a deliberate hub-and-spoke shape: a small public surface over many focused internal modules.
Dependency injection is a subsystem, not a feature
dependencies/utils.py is one of the largest components in the codebase. FastAPI's Depends() system — resolving nested dependencies, caching them per-request, extracting parameters — is effectively its own engine living in a two-file subpackage.
The _compat layer is how you support two Pydantic majors
The _compat module isolates every Pydantic v1/v2 difference behind one boundary, so the rest of the codebase imports compat shims instead of branching on versions inline. A textbook example of confining an external dependency's churn to a single module.
X-ray your own repo
This page is unedited archsteer xray output plus commentary. The same map of your codebase takes one command, runs locally, and never sends code anywhere: pip install archsteer && archsteer xray
FAQ
How is FastAPI structured internally?
As a thin hub-and-spoke layer over Starlette and Pydantic: routing.py and applications.py form the public hub, with focused subpackages for dependency injection (dependencies/), OpenAPI generation (openapi/), security schemes (security/), and Pydantic version compatibility (_compat/). The x-ray counts 48 components across 28 top-level modules with only 5 runtime dependencies.
What does FastAPI depend on?
Just five runtime packages: starlette (the ASGI toolkit that handles requests, responses, middleware and websockets), pydantic (validation and serialization), typing-extensions, typing-inspection, and annotated-doc. Everything else — servers, ORMs, template engines — is deliberately left to the user.
How was this architecture map generated?
By running `archsteer xray` (an open-source, MIT-licensed CLI) against the fastapi/ package directory of the public GitHub repo. It's read-only static analysis — no code is executed — and you can reproduce it on any repo with `pip install archsteer && archsteer xray`.
More x-rays
The architecture of Flask, x-rayed
An auto-generated architecture map of Flask: 24 components, the sansio core split, bluepri…
The architecture of HTTPX, x-rayed
An auto-generated architecture map of HTTPX: 23 underscore-private components, the pluggab…
The architecture of Starlette, x-rayed
An auto-generated architecture map of Starlette: 34 components, the middleware stack, and …
The architecture of Pydantic, x-rayed
An auto-generated architecture map of Pydantic: 104 components, the _internal core, the bu…