Architecture¶
Read this page when you want a mental model of how a single browser request becomes either a FastAPI handler or Streamlit traffic.
FluxLit combines FastAPI for HTTP APIs and Streamlit for interactive UIs behind one primary port and one FluxLit application object.
Request path¶
Client
→ Uvicorn (FluxLit gateway ASGI app)
├─ path starts with /api → FastAPI (prefix stripped inside the app)
└─ otherwise → HTTP/WebSocket reverse proxy → Streamlit (subprocess)
Streamlit’s own paths (/_stcore/..., etc.) appear on the public origin because the gateway forwards them transparently.
Sidecar runtime¶
Streamlit runs with
streamlit runon an ephemeral localhost port.Uvicorn serves the gateway on the user-facing host and port.
The gateway forwards non-API traffic to Streamlit, including WebSockets required by Streamlit’s protocol.
This matches Streamlit’s supported deployment model, avoids unsupported deep embedding until a stable ASGI embedding story exists, and keeps a clear boundary for testing and operations.
Processes and environment¶
Role |
Process |
Listens on |
|---|---|---|
Gateway |
One Uvicorn process (single worker for unified stack) |
Public |
Streamlit |
Child of the runtime |
Ephemeral localhost port (not exposed directly) |
The runtime sets FLUXLIT_* variables so Streamlit’s entry script knows the import target, API prefix, internal API base URL, and (from the parent) where to reach the Streamlit HTTP server for readiness checks. See Runtime-managed environment variables.
Operational endpoints¶
Under the configured API mount (default /api), the inner app exposes /healthz (liveness) and /readyz (readiness vs Streamlit). Public URLs are typically /api/healthz and /api/readyz.
These routes are registered with include_in_schema=False so they do not appear in Swagger/OpenAPI; your own API surface stays clean.
Streamlit UI routing¶
You register pages with
page()ordiscover_pages().The Streamlit entry script builds
st.Pageentries and runsst.navigation(...).run().The HTTP server does not route individual Streamlit pages; Streamlit maps URL paths to pages after the gateway forwards the request.
Principles¶
Pythonic: explicit, typed surface; ordinary FastAPI and Streamlit in user code.
Production-minded: proxy-friendly (
root_path, forwarded headers where configured), observable hooks (request ids forwarded to Streamlit on proxied HTTP/WebSocket, optional API and gateway access logging, readiness via/api/readyz), optional 0.10 allowlisted merge of selected browser header names onto the HTTP hop to Streamlit (default off; see Security architecture), and tunable gateway timeouts, body limits, and upstreamhttpxpool behavior viaFluxlitSettings/FLUXLIT_*(see Configuration).Honest about Streamlit: subprocess + WebSocket proxy until a native single-process model is proven.
Stable extension points¶
Prefer these public hooks over importing private runtime modules:
Need |
Public surface |
|---|---|
API routes, dependencies, OpenAPI |
|
Streamlit pages |
|
Streamlit → API calls |
|
JWT / OIDC / BFF auth |
|
URL-bound continuity |
|
Logging and redaction |
|
Tracing integrations |
|
Modules or names prefixed with _ are internal unless documented in the API
reference. Runtime modules under fluxlit.runtime may change to support sidecar
or reload behavior; wrap them in your own deployment script only when the CLI is
not enough.
Further product context: see the architecture and product plan in the repository.
TLS termination, reverse-proxy trust, and operator security checklists: Production TLS and edge headers · Secrets lifecycle · Security architecture.
Automated tests¶
Gateway routing, HTTP/WebSocket proxying, root_path, readiness (/api/readyz), and auth helpers are covered by Pytest (fast matrix, optional slow subprocess checks, Playwright E2E, and Docker-based proxy smoke). See Testing and Observability.