Development Long read Emperor
Hundreds of sites on one server?

Hundreds of sites on one server?

Emperor, vassal, and spawn mechanisms.

18 February 2026 19 min read
Share
X in

Introduction

On shared hosting or agency setups, hosting dozens of Django/Flask projects on one Linux server is common. Writing a separate systemd unit per project increases maintenance. uWSGI Emperor mode solves this with a central daemon.

Emperor watches a directory for .ini files; when a new file appears it starts a vassal process, when removed it terminates it. This is the classic architecture used by shared hosting providers.

This article covers Emperor setup, vassal ini templates, socket isolation, and graceful reload strategies.

What Is Emperor Mode?

Emperor is a separate uWSGI instance; it does not handle HTTP traffic, only manages vassals. It starts via /etc/uwsgi/emperor.ini and watches emperor = /etc/uwsgi/vassals.

Each vassal runs independently with its own module, socket, and process settings. If one vassal crashes, Emperor restarts it; other sites are unaffected.

[uwsgi]
emperor = /etc/uwsgi/vassals
uid = www-data
gid = www-data
master = true
vacuum = true
logto = /var/log/uwsgi/emperor.log

Vassal Ini Template

Create /etc/uwsgi/vassals/sitename.ini per site. virtualenv, chdir, and module are required. Socket path must be unique per site.

Use touch-reload to touch the .ini or a separate touch file during deploy for zero-downtime reload.

  • chdir: proje kök dizini
  • virtualenv: izole Python ortamı
  • socket: nginx uwsgi_pass hedefi
  • touch-reload: graceful yeniden yükleme
[uwsgi]
chdir = /var/www/site1
virtualenv = /var/www/site1/venv
module = site1.wsgi:application
socket = /run/uwsgi/site1.sock
chmod-socket = 660
processes = 2
master = true
touch-reload = /var/www/site1/reload.touch

Spawn Mechanism

spawn is Emperor's process for starting vassals. lazy-apps = true makes each worker load the app separately; required for C extensions and some frameworks.

The cheaper algorithm adjusts worker count dynamically; saves memory at low traffic. Configure cheaper carefully in Emperor environments.

[uwsgi]
lazy-apps = true
cheaper = 2
cheaper-initial = 1
cheaper-step = 1
cheaper-algo = spare

Multi-Site with Nginx

Define a separate server block and uwsgi_pass per site. Unix sockets are faster and more secure than TCP.

include uwsgi_params; loads the standard parameter set. Incorrect SCRIPT_NAME and PATH_INFO break Django URL routing.

server {
    server_name site1.example.com;
    location / {
        include uwsgi_params;
        uwsgi_pass unix:/run/uwsgi/site1.sock;
    }
}

Monitoring and Security

stats socket exposes Emperor and vassal metrics as JSON. Use uwsgi --connect-and-read on /run/uwsgi/stats.sock.

Each vassal can run as different uid/gid; consider chroot and namespace for tenant isolation. Forward Emperor logs to central logging.

Emperor ile yönetilen her vassal için ayrı socket, log ve touch-reload dosyası kullanın; çakışma üretimde felakete yol açar.

Deploy and Reload

On code deploy, touch reload.touch is enough; Emperor gracefully reloads the vassal. ini changes are detected automatically.

With systemd, a single uwsgi-emperor.service unit suffices; no separate service per site.

[Unit]
Description=uWSGI Emperor
After=network.target

[Service]
ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/emperor.ini
Restart=always

Conclusion

Emperor mode is a proven solution for multi-site Python hosting. Proper ini templates, socket isolation, and touch-reload dramatically reduce operational load.

For a single small project Emperor may be unnecessary complexity; with 5+ apps it is worth evaluating.