Execution model
Dexpot chooses its scheduler once when the module imports. The application keeps the same synchronous handlers in every mode.
| Runtime | Default serving model | Overload behavior |
|---|---|---|
Free-threaded CPython (sys._is_gil_enabled() == False) |
One process; each admitted connection owns a thread | Active connections are capped at 1,024 by default; excess connections receive 503 before thread creation |
| Standard GIL CPython | A bounded pool of CPU * 2 + 2 connection-owning threads |
The queue is capped at 2 * pool; excess connections receive 503 |
Standard GIL CPython with DEXPOT_WORKERS>1 |
POSIX SO_REUSEPORT processes, each with its own bounded pool |
Each worker sheds independently |
A worker owns a keep-alive connection until it closes. Idle keep-alive sockets are not returned to a shared admission queue.
Tune admission
Section titled “Tune admission”Set limits before the process imports Dexpot:
# Free-threaded process-wide active-connection capDEXPOT_MAX_CONNECTIONS=512 dexpot serve main:app
# Standard GIL pool and queueDEXPOT_POOL=16 DEXPOT_MAX_QUEUE=32 dexpot serve main:appDEXPOT_POOL=0 keeps automatic sizing. Negative pool sizes and nonpositive queue or connection limits fail during import, before a listener can open.
Process fan-out
Section titled “Process fan-out”On supported POSIX systems:
DEXPOT_WORKERS=4 dexpot serve main:appDEXPOT_WORKERS>1 requires POSIX fork and SO_REUSEPORT. Dexpot rejects the setting on unsupported platforms. Free-threaded builds intentionally remain single-process because their threads can execute Python in parallel.
Shutdown and supervision
Section titled “Shutdown and supervision”SIGINT and SIGTERM stop admission and allow active connections up to five seconds to drain. The standard-GIL supervisor restarts a worker that exits unexpectedly.
Compiled plans
Section titled “Compiled plans”Registration produces immutable EndpointPlan objects for binding, path conversion, and body and response codecs. Serving freezes those endpoints into one ApplicationPlan and a length-grouped RouterPlan before opening a listener. Late route registration fails instead of diverging from the plan traffic uses.