Zero-GIL Architecture & PyO3 Threads
How the GIL Works
Section titled “How the GIL Works”In standard CPython (3.11 & 3.12), the Global Interpreter Lock (GIL) prevents multiple OS threads from executing Python bytecode simultaneously.
However, the GIL only locks Python interpreter execution — it does NOT lock native C/Rust code. JustAPI exploits this by moving 95% of request processing into Rust, where the GIL is released.
The py.allow_threads Mechanism
Section titled “The py.allow_threads Mechanism”In justapi-core and PyO3 native bindings, the GIL is explicitly released during all I/O, routing, and validation:
// Rust releases GIL during I/O, routing, and DB operations:py.allow_threads(|| { // 1. Socket TCP read // 2. TLS rustls decryption // 3. Matchit radix trie path resolution // 4. Precompiled JSON Schema validation // 5. Rust sqlx database query // 6. serde_json response serialization});Because 95%+ of request processing occurs inside py.allow_threads, JustAPI achieves true multi-core CPU scaling even on Python 3.11 & 3.12.
Request Lifecycle (GIL States)
Section titled “Request Lifecycle (GIL States)”Client Request │ ▼┌──────────────────────────────────────┐│ Rust: Accept connection │ 🔴 No GIL needed (native tokio)│ Rust: TLS handshake (rustls) │ 🔴 No GIL needed│ Rust: HTTP parse (hyper) │ 🔴 No GIL needed│ Rust: Route match (matchit) │ 🔴 No GIL needed│ Rust: Middleware chain │ 🔴 No GIL needed│ Rust: JSON Schema validation │ 🔴 No GIL needed│ Rust: DB query (sqlx) │ 🔴 No GIL needed│ Rust: JSON serialize (serde_json) │ 🔴 No GIL needed│ ││ ▼│ PyO3: Acquire GIL │ 🟡 Brief GIL acquisition│ Python: Execute handler │ 🟡 GIL held│ PyO3: Release GIL │ 🟡 Release│ ││ ▼│ Rust: Write response │ 🔴 No GIL needed└──────────────────────────────────────┘Free-Threading Support (Python 3.13t & 3.14t)
Section titled “Free-Threading Support (Python 3.13t & 3.14t)”When compiled against Python 3.13t or 3.14t free-threaded builds (Py_GIL_DISABLED=1), PyO3 automatically disables GIL synchronization, allowing Python handler execution in gil_pool.rs to run fully parallel across all CPU cores.
# Run with free-threaded PythonPYTHON_GIL=0 python main.pyGIL Pool Architecture
Section titled “GIL Pool Architecture”The gil_pool subsystem manages a pool of GIL-bound worker threads:
- Incoming requests that need Python execution are dispatched to the GIL pool
- Each worker acquires the GIL, executes the Python handler, and releases it
- The pool size is auto-tuned based on workload
- Under the standard GIL (3.11/3.12), this provides fairness across requests
Performance Impact
Section titled “Performance Impact”On standard CPython 3.12:
| Scenario | RPS | GIL Contention |
|---|---|---|
| 100% Rust native path | 724,000 | None |
| Python handler (simple) | 60,000 | Low |
| Python handler (CPU-bound) | 12,000 | High |
| Free-threaded 3.13t | Scaling | None |
See Also
Section titled “See Also”- Native Fast Path — 100% Rust route execution
- PyO3 & FFI Safety — Safe crossing between Rust and Python
- Performance Tuning — Optimize your application