Overview
A high-level overview of Flasgo, its design goals, the main workflow it supports, and changes to review when upgrading.
Flasgo is an async-first Python web framework designed to combine Flask-style ergonomics with Django-inspired security defaults.
It is meant for developers who want a small, focused framework that still covers the real application path: HTTP, WebSockets, lifecycle, background tasks, security, testing, observability, and production deployment.
This documentation covers the released Flasgo 0.11.0 API on Python 3.14+. The release badge tracks published GitHub and PyPI metadata. If your installed package is older, follow the version checks and upgrades.
Flasgo 0.11.0 changes
Section titled “Flasgo 0.11.0 changes”Flasgo 0.11.0 bounds route matching, fixes validation and dispatch bugs, and updates the optional extras. Review these behaviour changes before upgrading:
- The
dbextra pins Alembic 1.20, which requires SQLAlchemy 2.0 or newer. Upgrade SQLAlchemy before usingflasgo db. jwt_backend()andencode_jwt()raiseValueErrorat configuration time for PEM, SSH, DER, or JWK-shaped HMAC secrets. Code that caughtjwt.InvalidKeyErrorfromencode_jwt()must catchValueErrorinstead.- The request and session implementations moved to the private
flasgo._requestandflasgo._sessionmodules.from flasgo.request import Requestandfrom flasgo.session import Sessionstill work, but code that imported underscore-prefixed helpers fromflasgo.requestorflasgo.session, patched names on those modules, or checkedRequest.__module__must change. Signed session cookies are unaffected. - Applications mounted under an ASGI
root_pathnow route requests whosepathincludes the prefix.request.pathis relative to the mount point, andDOCS_PATH,OPENAPI_PATH,METRICS_PATH, andOTEL_EXCLUDED_PATHSmust not include the root path. - The
jwtextra pins PyJWT 2.15.1, and theotelextra pins OpenTelemetry 1.45.1 with ASGI instrumentation 0.66b1.
0.11.0 also fixes these defects:
- Routes with several converters in one segment, such as
/<a>-<b>-<c>-<d>/end, match in time proportional to the path length times the route length instead of backtracking polynomially before authentication or rate limiting. - A dependency provider that returns an instance of the annotated dataclass is injected as-is instead of being rejected with
422. app.override_dependencies(...)now applies to requests made insidewith app.test_client().- A
Form()dataclass whose__post_init__raisesValueErrororTypeErrorproduces a422FormValidationError, matchingBody(). - Uploaded-file collections enforce fixed tuple lengths and member types, so
tuple[UploadedFile, UploadedFile]requires exactly two files. - A correctly signed JWT whose
exp,nbf, oriatoverflows an integer receives a401Bearer challenge instead of500. - Swagger UI requests the OpenAPI document through the mount prefix, and
configure_static(directory, url_path="/")serves files and generates their URLs.
Flasgo 0.10.0 changes
Section titled “Flasgo 0.10.0 changes”Flasgo 0.10.0 fixes correctness and security edge cases across the framework. Review these behaviour changes before upgrading:
- Settings reject unsupported
ALLOWED_HOSTSandCSRF_TRUSTED_ORIGINSentries at startup. Allowed hosts are hostnames, IP addresses, or.suffixpatterns;"*"is rejected. Bare CSRF host and suffix entries trust only the request’s own scheme, andSESSION_COOKIE_MAX_AGEmust be a positive integer. - Parameter markers belong on the outer annotation, as in
Annotated[str | None, Header()]; nested markers are rejected at registration. Routemethodsmust be a collection such asmethods=["POST"]. - Numeric query, header, and form values must use plain ASCII decimal syntax. JWT scopes must be individual scope tokens, and JWT
leewaymust be finite. after_requesthooks also run for 404, 405, and authentication or authorization denials. An authentication backend that raises produces HTTP 500 instead of 401.- 1xx, 204, and 304 responses must have empty bodies and no longer send
Content-TypeorContent-Length. An SSEheartbeatmust be shorter thanidle_timeout. - Templates configured with
enable_async=Truerender inside a running event loop throughawait app.render_template_async(...)orawait app.templates.render_async(...). - Response headers are case-insensitive,
Sessionis a full mutable mapping, and therequest,session, andcurrent_userproxies forward attribute writes such assession.modified = True. AsyncTestStreamis exported fromflasgo, and the test client follows browser and server behaviour more closely for paths, redirects, and cookie expiry.
The changelog lists every fix, including rate-limit headers, static files, OpenAPI output, SSRF host handling, and the development reloader.
Flasgo 0.9.1 changes
Section titled “Flasgo 0.9.1 changes”Flasgo 0.9.1 tightened validation and failure handling and extended optional metrics:
- Routing rejects ambiguous patterns at registration and gives specific routes precedence over catch-all routes.
- Settings require actual booleans, and session/CSRF cookie names are validated at startup.
- Session handling discards mutations from failed dispatch and validates responses before saving session state. Duplicate security cookies and CSRF headers are not accepted as unambiguous credentials.
- HTTP and WebSocket request-head limits run before tracing, routing, and session storage. WebSocket Host, Origin, and client-IP route limits also run before session loading.
- Streaming cleanup has a separate deadline and bounded active and pending work.
- Metrics distinguish response delivery, streams, backend calls, background work, event-loop lag, and framework failures. Applications can register custom metrics through
app.metrics_registry. - CLI checks preserve parseable JSON when application loading fails.
Flasgo 0.9.0 additions
Section titled “Flasgo 0.9.0 additions”The following APIs and operational checks were introduced in 0.9.0 and remain available in 0.11.0. Ordinary response coercion, signed-cookie sessions, and the process-local route limiter remain the defaults.
| Capability | Guide |
|---|---|
| Declared route policy, deployment warnings, and baseline comparisons | Policy and Deployment Checks |
| Nested HTTP route groups, inherited permissions, and URL generation | Blueprints and URL Generation |
| Yielding providers, request/function lifetimes, and isolated overrides | Request Data and Dependencies |
| Explicit output validation and public field filtering | Response Contracts |
| Async streams, SSE, NDJSON, and incremental tests | Streaming Responses |
| Redis/Valkey quotas and revocable server-side sessions | Shared Quotas and Sessions |
Response contracts and shared storage require explicit configuration. Review dependency cleanup and background-task boundaries when upgrading; see Request Data and Dependencies.
Core ideas
Section titled “Core ideas”- ASGI-native: Flasgo is built for async request handling and modern Python deployment.
- Python 3.14+ only: the framework uses the current language and tooling baseline instead of carrying legacy-runtime compatibility.
- Familiar, typed API: Routing stays close to the Flask mental model, with optional
Annotatedrequest binding, dataclass validation, and dependency injection. - Security by default: Host validation, CSRF protection, signed sessions, SSRF guards, request limits, hardened headers, and disabled-by-default CORS are part of the normal setup.
- Small surface area: The framework stays intentionally compact instead of turning into a giant abstraction layer.
What a typical Flasgo app looks like
Section titled “What a typical Flasgo app looks like”import osimport secrets
from flasgo import Flasgo, Request, Response, redirect
app = Flasgo( static_folder="static", settings={ "DEBUG": True, "SECRET_KEY": os.environ.get("FLASGO_SECRET_KEY", secrets.token_urlsafe(32)), "ALLOWED_HOSTS": {"127.0.0.1", "localhost"}, "CSRF_ENABLED": True, "SESSION_COOKIE_SECURE": False, "CSRF_COOKIE_SECURE": False, },)
@app.get("/")async def home(): return {"framework": "flasgo", "status": "ok"}
@app.post("/contact")async def contact(request: Request) -> Response: form = await request.form() if form.get("email"): return redirect("/thanks") return Response.json({"error": "email is required"}, status_code=400)With the default CSRF settings, unsafe requests such as POST must include a matching CSRF cookie/header pair and a valid Origin or Referer.
Local workflow
Section titled “Local workflow”Install and run a project with:
uv add flasgouv run flasgo run app.py --reloadFor development and testing, the main toolchain is:
uvrufftypytestuvicorn
Inspect the application without serving it:
uv run flasgo routes app.pyuv run flasgo openapi app.py --output openapi.jsonuv run flasgo check app.pyProduction posture
Section titled “Production posture”Flasgo is designed to run behind a production ASGI server with explicit secrets and host configuration.
Typical production expectations are:
DEBUG=FalseSECRET_KEYprovided through the environment- Real domain values in
ALLOWED_HOSTS - Secure cookies enabled over HTTPS
- Documentation endpoints enabled only where intentional
- Exact WebSocket origins and bounded messages
- Protected metrics, OpenTelemetry traces, and centralized structured logs
- Durable queues for critical post-response work
- Deployment behind a reverse proxy or platform edge
Continue reading
Section titled “Continue reading”- Start with Getting Started
- Learn Request Data and Dependencies
- Read What is Flasgo?
- Review Security Architecture
- Check Development and Deployment
Sources: