Quart Async Flask — Core Concepts
What Quart is
Quart is a Python ASGI web framework that reimplements the Flask API. Created by Phil Jones (pgjones), it was later adopted by the Pallets organization — the same group that maintains Flask, Jinja2, and Werkzeug. This gives Quart a unique position: it’s the officially recognized async alternative to Flask.
The key idea: if you know Flask, you know Quart. The API is intentionally compatible. Route decorators, blueprints, template rendering, request/response objects, error handlers — they all work the same way. The difference is that handlers can (and should) be async def instead of def, and the underlying protocol is ASGI instead of WSGI.
What changes vs. Flask
Handlers become async:
# Flask
@app.route("/users")
def list_users():
users = db.query(User).all()
return jsonify(users)
# Quart
@app.route("/users")
async def list_users():
users = await db.fetch_users()
return jsonify(users)
WSGI → ASGI: Flask runs on WSGI servers (gunicorn, waitress). Quart runs on ASGI servers (hypercorn, uvicorn). This enables WebSockets, HTTP/2, and server-sent events.
WebSocket support is built in: Flask doesn’t natively support WebSockets. Quart does:
@app.websocket("/ws")
async def ws():
while True:
data = await websocket.receive()
await websocket.send(f"echo: {data}")
Server-Sent Events (SSE) work naturally:
@app.route("/stream")
async def stream():
async def generate():
while True:
data = await get_update()
yield f"data: {data}\n\n"
return generate(), {"Content-Type": "text/event-stream"}
What stays the same
The amount that stays the same is remarkable:
- Blueprints for modular app organization
- Jinja2 templates with
render_template() - Request/response objects with the same attributes and methods
url_for()for URL generation- Error handlers with
@app.errorhandler() - Before/after request hooks
- Configuration via
app.config - Testing with a test client (async version)
- Extensions — many Flask extensions work with Quart directly or have Quart equivalents
The migration path
Migrating a Flask app to Quart typically involves:
- Change imports:
from flask import Flask→from quart import Quart - Add
asyncto handlers:def index():→async def index(): - Add
awaitto I/O calls: Use async database drivers, async HTTP clients - Switch server: gunicorn → hypercorn or uvicorn
- Update extensions: Check which Flask extensions need Quart-specific versions
The non-trivial part is step 3. Synchronous database drivers (like psycopg2, pymysql) block the event loop. You need async alternatives (asyncpg, aiomysql) to get the performance benefits. Without async I/O, Quart won’t actually be faster than Flask.
When Quart makes sense
Migrate to Quart when:
- Your Flask app has I/O-bound bottlenecks (database queries, API calls, file operations)
- You need WebSocket support without adding Flask-SocketIO
- You want server-sent events for real-time features
- You’re already investing time in refactoring and want async benefits
- Your team knows Flask and doesn’t want to learn a new framework
Stay with Flask when:
- Your app is CPU-bound (async won’t help)
- You rely on Flask extensions that have no async equivalents
- Your app works fine at current scale
- The migration cost exceeds the performance benefit
Choose FastAPI instead when:
- Starting a new project from scratch
- You want automatic data validation and OpenAPI docs
- You don’t have existing Flask code to migrate
The Hypercorn connection
Quart’s creator also created Hypercorn, an ASGI server designed to work well with Quart. Hypercorn supports HTTP/1.1, HTTP/2, and HTTP/3 (QUIC). While you can run Quart on uvicorn, Hypercorn is the natural pairing and supports features like HTTP/2 server push.
Common misconception
People sometimes think Quart is “slower Flask” because it adds async overhead for simple requests. For purely synchronous code, this is true — there’s a small overhead from the async machinery. But Quart’s value emerges under concurrent load. A Flask app serving 100 simultaneous database queries needs 100 threads. A Quart app does the same with one thread and coroutines, using a fraction of the memory.
The one thing to remember: Quart is the async Flask — same API, same patterns, but built on ASGI for concurrent request handling, WebSockets, and server-sent events. It’s the lowest-friction path from synchronous Flask to async Python.
See Also
- Python Aiohttp Client Understand Aiohttp Client through a practical analogy so your Python decisions become faster and clearer.
- Python Api Client Design Why building your own API client in Python is like creating a TV remote that only has the buttons you actually need.
- Python Api Documentation Swagger Swagger turns your Python API into an interactive playground where anyone can click buttons to try it out — no coding required.
- Python Api Mocking Responses Why testing with fake API responses is like rehearsing a play with stand-ins before the real actors show up.
- Python Api Pagination Clients Why APIs send data in pages, and how Python handles it — like reading a book one chapter at a time instead of swallowing the whole thing.