Python aiohttp Server — Core Concepts
What aiohttp Server Is
aiohttp is a Python library for building asynchronous HTTP servers (and clients) on top of asyncio. Unlike Flask or Django, which traditionally use a thread-per-request model, aiohttp handles requests with coroutines inside a single-threaded event loop.
This makes it especially effective for applications that spend most of their time on network I/O — API gateways, chat servers, webhook receivers, or microservices that aggregate data from multiple backends.
Setting Up a Basic Server
A minimal aiohttp server defines request handlers as async functions and maps them to URL paths:
from aiohttp import web
async def hello(request):
name = request.match_info.get("name", "World")
return web.Response(text=f"Hello, {name}!")
app = web.Application()
app.router.add_get("/", hello)
app.router.add_get("/{name}", hello)
web.run_app(app, port=8080)
Each handler receives a Request object and must return a Response. Because handlers are coroutines, they can await database queries, HTTP calls, or any async operation without blocking other requests.
Routing and Request Handling
aiohttp supports path variables, query parameters, and multiple HTTP methods:
- Path variables:
/{user_id}→request.match_info["user_id"] - Query params:
/search?q=python→request.query["q"] - JSON body:
data = await request.json() - Form data:
data = await request.post()
You can organize routes into groups using RouteTableDef:
routes = web.RouteTableDef()
@routes.get("/users/{id}")
async def get_user(request):
...
@routes.post("/users")
async def create_user(request):
...
app.router.add_routes(routes)
Middleware
Middleware wraps every request/response cycle. Common uses: logging, authentication, error handling, CORS.
@web.middleware
async def logging_middleware(request, handler):
print(f"→ {request.method} {request.path}")
response = await handler(request)
print(f"← {response.status}")
return response
app = web.Application(middlewares=[logging_middleware])
Middleware is applied in order — the first middleware in the list wraps all subsequent ones.
Application Lifecycle
aiohttp provides startup and cleanup hooks for managing resources like database connections:
async def init_db(app):
app["db"] = await create_pool(dsn="...")
async def close_db(app):
await app["db"].close()
app.on_startup.append(init_db)
app.on_cleanup.append(close_db)
This pattern ensures connections are established before the first request and properly closed on shutdown.
WebSocket Support
Built-in WebSocket handling is a key differentiator from synchronous frameworks:
async def ws_handler(request):
ws = web.WebSocketResponse()
await ws.prepare(request)
async for msg in ws:
if msg.type == web.WSMsgType.TEXT:
await ws.send_str(f"Echo: {msg.data}")
return ws
Because WebSockets are long-lived connections, async handling is essential — a thread-per-connection model would exhaust resources quickly with hundreds of connected clients.
Common Misconception
“aiohttp replaces Flask/Django for all use cases.” Not quite. aiohttp lacks the batteries-included ecosystem — no built-in ORM, admin panel, or template engine. It excels at I/O-heavy, real-time, or high-concurrency scenarios. For traditional CRUD web apps with server-rendered pages, Django or Flask with async workers may be more productive.
One thing to remember: aiohttp server lets you write web handlers as async coroutines, so one Python process can handle thousands of concurrent connections by never blocking on I/O.
See Also
- Python Server Sent Events Patterns How Python servers push live updates to browsers using a one-way radio channel that is simpler than WebSockets.
- Python Websocket Scaling Why keeping thousands of live chat connections open in Python is like managing a phone switchboard that never hangs up.
- Ci Cd Why big apps can ship updates every day without turning your phone into a glitchy mess — CI/CD is the behind-the-scenes quality gate and delivery truck.
- Containerization Why does software that works on your computer break on everyone else's? Containers fix that — and they're why Netflix can deploy 100 updates a day without the site going down.
- Python 310 New Features Python 3.10 gave programmers a shape-sorting machine, friendlier error messages, and cleaner ways to say 'this or that' in type hints.