We run Django + gunicorn + DRF in production. Our P95 API latency was around 5 seconds but OpenTelemetry could only explain about 3 seconds. The remaining 2 seconds were completely unaccounted for. No slow queries, no slow third-party calls. Just missing time.
We tried Datadog, we tried py-spy. Neither could explain the gap. So I built an eBPF profiler that hooks into CPython internals from kernel space.
Here’s what we found hiding underneath our Django app:
GIL contention from URL resolution. Django’s URL resolver was holding the GIL while resolving routes. We have a large urlconf and this was adding up on every request. Since our URLs are static, we added URL caching and cut GIL wait by 80%. The tool showed us both which thread was holding the GIL and which thread was waiting, with full Python stacks for both. No other profiler showed us this.
GC gen-2 pauses. Django loads a lot of objects at startup. Models, middleware, URL patterns, template engines. Gen-2 GC was walking 1.5M objects on each collection. Worst case was 1.27 seconds. We added gc.freeze() in our gunicorn post_fork hook to freeze startup objects. Worst-case GC pause dropped to 88ms.
Gunicorn handoff latency. When workers are busy with GIL contention or GC, new requests pile up in gunicorn’s queue. Our tool measures exact handoff time. Before fixes: requests waited seconds in queue. After fixes: single-digit milliseconds.
Off-CPU from Kafka. One of our DRF views was pushing to Kafka synchronously. The thread was blocking for 130ms per request. Completely invisible in OpenTelemetry because it wasn’t instrumented. Our tool showed the full stack: views.py:post > sessions.py:post > socket.py:readinto. We moved it to async and the off-CPU time disappeared.
The tool uses eBPF uprobes on CPython’s take_gil/drop_gil and gc_collect_main. No code changes to your Django app. Just point it at your gunicorn PIDs and run.
CPython 3.11 only for now. Open source under Apache 2.0.
Has anyone else run into unexplained latency gaps in their Django app? Curious what tools you use to debug this.