Blog
Managing Multiple Python Apps with uWSGI Emperor Mode
Learn how uWSGI Emperor mode lets you manage multiple Python apps with isolated environments and automatic reloads.
Published by Tasadduq Burney
27 May 2026, 09:24 UTC
3 min114.6K views0

The problem: keeping many Python services up‑to‑date without manual restarts
When you run several Flask or Django apps on the same host, each needs its own virtual environment, possibly different Python versions, and you want to update one without touching the others. Doing this by hand — stopping a service, editing its config, starting it again — is error‑prone and creates downtime for the unchanged apps.
How uWSGI Emperor mode solves it
The Emperor is a master uWSGI process that watches a directory (the vassals folder) for .ini files. Each file describes one vassal app. When the Emperor sees a new or changed file it spawns a fresh vassal process; when the file is removed it shuts that vassal down. Because each vassal runs in its own address space, you can point them at different virtual environments or Python interpreters.
Under the hood the Emperor relies on the kernel’s inotify subsystem to get file‑system events, so it reacts instantly to touch, edits, or moves without polling.
Worked example: two Flask apps
1. Create the vassal directory (needs root or a user with sudo):
sudo mkdir -p /etc/uwsgi/vassals
2. Add a vassal config for app1 (/etc/uwsgi/vassals/app1.ini):
[uwsgi]
chdir = /opt/app1
module = wsgi:application
home = /opt/app1/venv # virtual‑env path
socket = /tmp/app1.sock
chmod-socket = 660
vacuum = true
3. Do the same for app2 (/etc/uwsgi/vassals/app2.ini) pointing to its own directory and venv.
4. Start the Emperor (run as a user that can read the vassal files and write to the log):
uwsgi --emperor /etc/uwsgi/vassals --daemonize /var/log/uwsgi-emperor.log
5. Verify startup: grep -i spawned /var/log/uwsgi-emperor.log should show lines for both vassals.
6. To update only app1, touch its config:
sudo touch /etc/uwsgi/vassals/app1.ini
7. Watch the log: you will see a graceful reload message for app1 only, while app2 continues serving requests.
Trade‑off and limitation
The Emperor adds a small resident memory footprint (the master process plus the inotify watch). More importantly, it requires a filesystem that supports inotify. Some container runtimes or network filesystems (e.g., NFS without proper options) may drop or delay events, causing the Emperor to miss changes. In those environments you must either enable polling (--emperor-poll-interval) or rely on external process managers.
You can check whether inotify is working by looking at the Emperor log after a touch; if no reload appears after a few seconds, increase the poll interval as a fallback:
uwsgi --emperor /etc/uwsgi/vassals --emperor-poll-interval 5 --daemonize /var/log/uwsgi-emperor.log
Actionable closing
If you operate more than one Python service on a host, give Emperor mode a try:
- Place each app’s .ini in a dedicated vassals directory.
- Start the Emperor with appropriate permissions and a log file.
- Validate that a simple touch triggers a reload only for the touched vassal.
- Monitor the Emperor log for any missing‑event warnings and enable polling if needed.
With these steps you get isolated, independently reloadable applications without writing custom restart scripts.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.