Diagnosing uWSGI Stuck Workers: Harakiri, Stats Server, and Practical Fixes
When uWSGI workers hang, use the stats server to spot frozen workers, check harakiri logs, and monitor memory. Tweak harakiri, enable graceful reloads, and adjust the cheaper strategy to keep your app responsive.
25 Jan 2026, 13:09 UTC

Recognizable Symptom
When HTTP requests hang and the uWSGI stats interface shows workers with a static request count and run_time, the most common culprit is a worker that has stopped progressing. The issue can stem from database locks, slow external calls, or filesystem I/O that blocks the worker’s thread.
Diagnostic Table
| Symptom | Likely Cause | Diagnostic Check | Fix |
|---|---|---|---|
Requests stall; stats show frozen request_count and run_time |
Application blocking on DB lock, external HTTP, or file I/O | Poll the stats server for workers whose counters stop incrementing | Investigate application code, add timeouts, or adjust DB connection pool |
Log entry: harakiri: worker killed after N seconds |
Request exceeded the --harakiri limit |
Match log timestamp, worker PID, and request URI to trace the slow request | Increase --harakiri or refactor the slow path; enable --harakiri-verbose for details |
| New connections queue or fail while CPU idle | All workers stuck or listen socket backlog exhausted | Check listen_queue via stats; compare active workers to --processes and --cheaper |
Adjust --cheaper strategy or increase backlog size |
| Worker RSS steadily grows with stable throughput | Memory leak in app or a loaded uWSGI plugin | Sample /proc/<pid>/status for VmRSS before and after a reload |
Enable --reload-on-rss or --reload-on-as; investigate code or plugin |
Ordered Checks
- Verify the stats server is reachable. Run:
This confirms the stats endpoint is active and you have network access.curl -s http://127.0.0.1:9191/ | head - Identify frozen workers. Query the JSON stats and filter workers where
request_countandrun_timehave not changed for >30 s. Example usingjq:while true; do stats=$(curl -s http://127.0.0.1:9191/) echo "$stats" | jq '.workers[] | select(.run_time==0)' sleep 30 done - Check the uWSGI log for harakiri or segfault entries. Example log snippet:
Cross‑reference the timestamp and worker PID with the stats snapshot.2026-11-12 14:35:12,001 INFO: harakiri: worker 7 killed after 60 seconds - Inspect memory usage. For a suspected leaking worker, run:
Compare values before and after a graceful reload.cat /proc/12345/status | grep VmRSS
Fixes Tied to Findings
- Harakiri tuning. Set a conservative
--harakirivalue that covers normal request time but allows you to capture slow paths. For example:
This logs the full stack of the worker when it is killed.--harakiri 120 --harakiri-verbose - Graceful reload on memory thresholds. Add:
to restart workers that exceed 200 MB RSS or 80 % of total address space.--reload-on-rss 200000 --reload-on-as 0.8 - Cheaper strategy adjustment. If the listen queue is full, increase
--cheaperor set--cheaper-initialto spawn more workers during spikes. - Application timeouts. Wrap external calls with timeouts and add proper exception handling. For database queries, use connection pool timeouts.
Escalation Criteria
| Condition | Action |
|---|---|
| Harakiri fires on every deploy | Review application logic; consider a more granular --harakiri per request group.
|
| Stats server unresponsive | Check uWSGI process health; if it hangs, restart the service. |
| Memory growth >200 MB per worker for >10 min | Capture a SIGQUIT backtrace, analyze stack frames, and involve platform or security teams. |
Example uWSGI Configuration
[uwsgi]
# Basic settings
module = myapp.wsgi
master = true
processes = 4
socket = /run/uwsgi.sock
chmod-socket = 664
vacuum = true
# Stats server on a Unix socket
stats = /tmp/uwsgi-stats.sock
stats-http = 127.0.0.1:9191
# Harakiri and verbose logging
harakiri = 120
harakiri-verbose = true
# Memory‑based worker recycling
reload-on-rss = 200000
reload-on-as = 0.8
# Cheaper strategy for dynamic load
cheaper = 1
cheaper-initial = 2
cheaper-step = 1
Verification Checklist
- Run
uwsgi --versionto confirm the binary and plugin set. - Confirm the stats socket file exists and is readable by the web process.
- Use
curl http://127.0.0.1:9191/to fetch stats; validate JSON structure. - Check logs for
harakirientries and correlate with stats. - Monitor
/proc/<pid>/statusfor RSS growth over a 15‑minute window. - After applying a fix, repeat the checks to ensure the symptom is resolved.
Practical Takeaway
When uWSGI workers appear stuck, start by polling the stats server for workers whose counters stop moving. Pair that with log inspection for harakiri events and memory checks. Tuning --harakiri, enabling graceful reloads, and adjusting the cheaper strategy usually resolve the issue. If the problem persists, capture a backtrace and involve platform support.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.