Server Behavior¶
This page describes runtime behavior that matters during incidents and scale events.
Connection lifecycle¶
- accept connection
- parse request(s)
- execute ASGI app
- write response
- keep alive or close
For WebSocket upgrades, flow switches from HTTP request lifecycle to websocket event lifecycle.
Limits and overload behavior¶
--limit-concurrencycaps in-flight work- excess load receives
503 Service Unavailable - request/response parser limits protect memory and CPU
Header behavior¶
- optional default
serveranddateheaders - connection handling based on protocol/headers
- response content length/chunking normalized on write
Graceful shutdown model¶
On shutdown signal, Palfrey:
- stops accepting new connections
- waits for active tasks/connections to drain
- enforces
--timeout-graceful-shutdownwhen set - runs lifespan shutdown when enabled
Graceful handling example:
from __future__ import annotations
import asyncio
async def app(scope, receive, send):
"""Simulate work and return once complete."""
if scope["type"] != "http":
return
await asyncio.sleep(0.2)
body = b"finished"
await send(
{
"type": "http.response.start",
"status": 200,
"headers": [
(b"content-type", b"text/plain"),
(b"content-length", str(len(body)).encode("ascii")),
],
}
)
await send({"type": "http.response.body", "body": body})
Worker recycle behavior¶
--limit-max-requests and jitter can be used to rotate workers over time and avoid synchronized restarts.
Plain-language explanation¶
Server behavior defines what happens when things are busy or broken. The goal is controlled degradation, not sudden failure.