Skip to content
19 changes: 19 additions & 0 deletions docs/content/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,23 @@ Choose a worker type based on your application's needs.
gunicorn myapp:app -k tornado
```

=== "Interpreter (Experimental)"

!!! warning "Experimental — requires Python 3.14+"

**Sub-interpreter** worker using `InterpreterPoolExecutor`. Each request runs
in its own sub-interpreter with an independent GIL, enabling true CPU
parallelism without forking extra processes.

- True parallelism for CPU-bound workloads
- No keep-alive support
- Hooks (`ssl_context`, `pre_request`, `post_request`) are not supported
- See the [Interpreter Worker](ginterpreter.md) guide for details

```bash
gunicorn myapp:app -k ginterpreter --threads 4
```

## Comparison

| Worker | Concurrency Model | Keep-Alive | Best For |
Expand All @@ -134,13 +151,15 @@ Choose a worker type based on your application's needs.
| `gevent` | Greenlets | ✅ | I/O-bound, WebSockets, streaming |
| `eventlet` | Greenlets | ✅ | **Deprecated** - use `gevent` instead |
| `tornado` | Tornado IOLoop | ✅ | Native Tornado applications |
| `ginterpreter` *(experimental)* | Sub-interpreters | ❌ | CPU-bound apps on Python 3.14+ |

!!! tip "Quick Decision Guide"

- **Simple app behind nginx?** → `sync` (default)
- **Need keep-alive or moderate concurrency?** → `gthread`
- **WebSockets, streaming, long-polling?** → `gevent` or ASGI worker
- **FastAPI, Starlette, or async framework?** → ASGI worker
- **CPU-bound and on Python 3.14+?** → `ginterpreter` *(experimental)*

## When to Use Async Workers

Expand Down
51 changes: 51 additions & 0 deletions docs/content/ginterpreter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Interpreter Worker

!!! warning "Experimental"
The `ginterpreter` worker is experimental and requires Python 3.14+. The API
and behavior may change in future releases.

The interpreter worker uses Python's `InterpreterPoolExecutor` to handle each
request in a separate sub-interpreter. Each sub-interpreter runs in its own
thread with an independent GIL, enabling true CPU parallelism without multiple
processes.

## Quick Start

```bash
gunicorn myapp:app --worker-class ginterpreter --threads 4
```

Or in a configuration file:

```python
# gunicorn.conf.py
worker_class = "ginterpreter"
threads = 4
```

## Configuration

The interpreter worker uses the standard gunicorn settings. The most relevant ones:

| Setting | Default | Description |
|---------|---------|-------------|
| `threads` | `1` | Number of sub-interpreters (i.e. concurrent requests per worker) |
| `workers` | `1` | Number of worker processes |
| `timeout` | `30` | Request timeout in seconds |
| `graceful_timeout` | `30` | Time to wait for in-flight requests on shutdown |

## Known Limitations

The following features are **not supported**:

- **`ssl_context` hook** — SSL contexts cannot be shared across sub-interpreters. Built-in SSL via `certfile`/`keyfile` works normally.
- **`pre_request` / `post_request` hooks** — Callables cannot be passed to sub-interpreters.
- **Keepalive connections** — Each connection is closed after the response.
- **HTTP/2**
- **Sendfile**
- **`max_requests` / `max_requests_jitter`**

## See Also

- [Settings Reference](reference/settings.md) - All available settings
- [Design](design.md) - Worker architecture overview
1 change: 1 addition & 0 deletions gunicorn/workers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
"tornado": "gunicorn.workers.gtornado.TornadoWorker",
"gthread": "gunicorn.workers.gthread.ThreadWorker",
"asgi": "gunicorn.workers.gasgi.ASGIWorker",
"ginterpreter": "gunicorn.workers.ginterpreter.InterpreterWorker",
}
Loading
Loading