Part 2 · 2 chapters · ~12 min
App Servers and Process Managers
Why app servers exist, the WSGI, ASGI and Rack contracts, Gunicorn and Uvicorn workers, Puma processes and threads, Node as its own server, embedded Tomcat and Netty with virtual threads, sizing workers, and process managers (PM2, systemd, supervisord) against orchestrators.
3
Process, thread and event-loop servers
| runtime | app server | sizing rule of thumb |
|---|---|---|
| Python (Django, Flask) | Gunicorn sync or gthread | workers ≈ 2 × cores + 1 for sync; threads for IO-heavy apps |
| Python async (FastAPI, Django ASGI) | Uvicorn (alone or as Gunicorn workers) | one worker per core; async inside |
| Ruby (Rails) | Puma | workers = cores; 3-5 threads each; DB pool ≥ threads |
| Node | itself | one process per core or per container |
| Java (Spring Boot) | embedded Tomcat, Jetty, Undertow or Netty | one JVM per container; tune thread pools, or use virtual threads |
| Go | net/http in the binary | one process; goroutines per request |
| PHP | PHP-FPM | pm.max_children from memory per worker |
APP SERVERS: HOW REQUESTS REACH YOUR CODE
process, thread and event-loop models
swipe the figure sideways, or tap expand for full screen
1/5
why an app server
Most languages do not serve HTTP efficiently from application code alone. An app server manages processes or threads, speaks HTTP (or a gateway protocol such as WSGI, ASGI, Rack) and hands each request to your framework.
processes, threads and HTTP handled for youWSGI, ASGI and Rack are the contracts
4
Process managers versus orchestrators
| tool | does | use when |
|---|---|---|
| systemd | starts, restarts, limits resources, collects logs on Linux hosts | VMs and bare metal; the default supervisor |
| PM2 | Node process management, cluster mode, zero-downtime reloads, logs | Node on VMs |
| supervisord | generic process supervision | older setups, several processes in one container (avoid) |
| Kubernetes, ECS, Nomad | schedule containers across machines, restart, scale, roll out | more than a handful of services |
Never stack them: inside Kubernetes, run the app server directly as the container's process. A process manager inside a pod hides crashes from the orchestrator and fights it over restarts.