Scale uWSGI workers down at idle with cheaper for a Python WSGI deployment
Use uWSGI's cheaper subsystem to scale Python WSGI workers between a minimum and maximum. Configure master mode, workers, cheaper, cheaper-initial and cheaper-algo, then verify idle reduction and load scaling with logs or the stats server.
04 Feb 2026, 00:34 UTC

Desired outcome
Keep a Python WSGI app responsive under bursts while using less memory when idle. uWSGI's cheaper subsystem lets the master process vary the number of worker processes between a minimum and a maximum instead of running a fixed pool 24/7.
With cheaper you set a max worker count for peak load and a cheaper minimum for idle. The master adds workers when demand rises and removes idle workers after a quiet period. The practical gain is lower resident memory at night or off-peak without sacrificing burst capacity.
Prerequisites
- uWSGI installed from pip or a distro package, and a working WSGI app that imports via
module = myapp:app. Verify the binary exists and the cheaper options are recognized in your version. - A functional uWSGI instance with master mode. cheaper requires
master = true; without a master the directives are silently ignored. - Access to reload or restart the service as the user running uWSGI, typically root or a service account. If you use emperor/vassal, the vassal ini is the target.
- Optional stats endpoint for observation:
stats = 127.0.0.1:1717enables uwsgitop or curl inspection of worker counts.
Note: uWSGI upstream is in maintenance mode with minimal new development. Confirm the version you run supports cheaper and matches the option names you plan to use.
Focused procedure
Check current version and options
Run on the host where uWSGI executes:
uwsgi --version
uwsgi --help | grep -i cheaperThis confirms the binary accepts cheaper-related ini keys. Do not assume defaults across versions.
Edit the vassal ini
Example file /etc/uwsgi/apps/myapp.ini. Keep your existing socket, WSGI and logging settings and add:
[uwsgi]
module = myapp:app
master = true
socket = /run/uwsgi/myapp.sock
chmod-socket = 660
vacuum = true
workers = 8
cheaper = 2
cheaper-initial = 2
cheaper-algo = spare
Meaning:
workers = 8is the maximum worker processes.cheaper = 2is the minimum active workers when idle.cheaper-initial = 2spawns only the minimum at startup instead of the max.cheaper-algo = spareis the default algorithm that adds a worker when all current workers are busy and kills idle ones after a quiet period.
Alternative algorithms exist, e.g., cheaper-algo = backlog reacts to listen queue depth. Choose based on workload shape.
Reload the instance
With systemd:
sudo systemctl reload uwsgi-myappOr direct invocation for testing:
sudo uwsgi --ini /etc/uwsgi/apps/myapp.iniReload is preferred to preserve the master process. A full restart is required if you changed master mode.
Risk: an aggressively low cheaper value can cause latency spikes on sudden load because worker spawn is not instantaneous, especially for apps with slow imports or connection setup.
Expected checks
Idle state
After startup and a quiet period, the process tree should settle near the cheaper minimum. With stats enabled you can inspect worker count via the stats socket. Logs typically contain cheaper-related messages when workers are killed or respawned.
Under load
Generate controlled concurrent requests against the app endpoint using a tool like wrk or ab. Observe worker count rising toward the max defined by workers. The master spawns additional workers as demand increases.
Scale down
Stop the load and wait for the idle timeout. Worker count should decrease back toward the cheaper minimum and resident memory of the master tree should drop relative to a fixed pool.
Verification steps to run manually:
- Confirm cheaper options are accepted at startup with no ini parse errors.
- Watch worker count during idle, load, and cooldown via logs or the stats server.
- Confirm memory usage is lower at idle compared to a fixed
workers = 8configuration.
Recovery options
If scaling misbehaves, e.g., thrashing spawn/kill or latency spikes:
- Increase
cheaperto raise the idle floor, reducing spawn frequency. - Change
cheaper-algoto backlog for queue-driven workloads. - Revert to fixed workers by removing
cheaper,cheaper-initialandcheaper-algolines, keepingworkers = 8. Restart the instance to restore stable behavior.
A full restart of the uWSGI instance restores the last known-good config. Keep a backup of the ini before changes.
Limitations
cheaper requires master mode. Worker spawn latency means cheaper is not suitable for workloads that need instant scale from zero. Option names and behavior are version-sensitive; verify against the installed uWSGI version rather than documentation for a different release.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.