Middleware
Middleware in Aegis is auto-discovered. Drop a Python file into
app/components/backend/middleware/ that exports a
register_middleware function, and it runs on the next start. No
central registry, no import order to manage.
The Contract
# app/components/backend/middleware/your_middleware.py
from fastapi import FastAPI
def register_middleware(app: FastAPI) -> None:
app.add_middleware(YourMiddleware, ...)
That's the whole API. A few rules worth knowing:
register_middlewareis synchronous. It runs at app build time, before the event loop starts. Usedef, notasync def. If you need async setup, do it in a startup hook and read the result from settings or a module-level cache insideregister_middleware.- Files beginning with
_are skipped. Use this for shared helpers in the directory. - Registration order is not guaranteed. If two middleware modules
must compose in a specific order, define both classes in the same
file and register them in one
register_middlewarecall so the order is explicit. - A module that doesn't export
register_middlewareis silently ignored. Intentional. If your new middleware never fires, check the function name and that the filename isn't prefixed with_. - Import errors are logged, not raised. One broken middleware won't take down the boot. Watch the logs.
What Ships In The Templates
The following middleware come with every generated project. Some are
gated on the services you selected at aegis init time.
Performance
Registered always. Times every HTTP request and surfaces live
per-endpoint stats through the Server modal's Performance tab and
/api/v1/metrics/*. In-process and ephemeral, with no external
dependencies.
See Performance Middleware for what you see, how to read it, and when to reach for observability instead.
CORS
Registered always. Out of the box, allows the local Flet dev frontend and the FastAPI docs UI to call the backend with credentials. To open up for a deployed frontend, widen the allowed origins list in the CORS module, or replace the hard-coded values with a setting.
OAuth Session
Registered when the auth service is included with at least one OAuth provider enabled. Holds the OAuth state and PKCE verifier between the redirect to the provider and the callback. Without it, the OAuth round-trip can't be verified.
Two settings to know:
OAUTH_SESSION_SECRET: signing secret for the session cookie.SESSION_COOKIE_SECURE: explicit override of the cookie's secure flag. Defaults to secure in every environment exceptAPP_ENV=dev. Set tofalsefor prod-over-plain-HTTP setups where browsers would otherwise drop the cookie.
Logfire Tracing
Registered when the observability component is included. Wires up
Logfire instrumentation for FastAPI, HTTPX, and (if present)
SQLAlchemy and Redis. When LOGFIRE_TOKEN is unset, traces still
run locally and nothing is shipped to Logfire cloud.
Polling endpoints used by the dashboard are excluded from tracing on purpose; otherwise they'd drown out every other span.
Authoring A Custom Middleware
Drop one file, export one function. Example: inject and echo a request ID.
# app/components/backend/middleware/request_id.py
import uuid
from fastapi import FastAPI, Request
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import Response
class RequestIDMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next) -> Response:
request_id = request.headers.get("X-Request-ID") or str(uuid.uuid4())
request.state.request_id = request_id
response = await call_next(request)
response.headers["X-Request-ID"] = request_id
return response
def register_middleware(app: FastAPI) -> None:
app.add_middleware(RequestIDMiddleware)
Restart the backend, and the Lifecycle tab on the Server card shows your new middleware in the stack.
Musings: Backend Middleware Auto-Discovery (November 22nd, 2025)
I'm not sure how I ultimately feel about the auto-discovery middleware pattern. I don't have enough experience with FastAPI plugins yet, but it's something I'm thinking about as the architecture evolves.
The current approach works well for explicit component registration, but auto-discovery could reduce boilerplate at the cost of making the registration flow less obvious. Trade-offs worth considering as Aegis Stack matures.
See Also
- Lifecycle for setup work that needs the event loop.
- Authentication Integration for the rate-limiter dependency pattern, which lives alongside middleware but is consumed as a FastAPI dependency rather than registered as one.