Self-hosting: Docker, configuration and scaling
Self-hosted n8n can be installed several ways: Docker, Docker Compose, npm, a one-line setup script, or ready-made templates on cloud providers (AWS, Azure, Google Cloud Run, Kubernetes, Hetzner, Digital Ocean and others).
A single Docker container is enough for learning. Docker Compose fits production better, because a database has to run alongside n8n.
The minimum for production:
- An external database (usually PostgreSQL) — the default SQLite is for a single instance and light load
- HTTPS and a proper domain — webhook URLs are handed to external systems
- Managing the encryption key — credentials are encrypted with it
- Execution data pruning — old executions bloat the database
- Backups — the database and the encryption key together
Configuration is done with environment variables. n8n has a large set of them, grouped by topic: database, executions, endpoints, binary data, credentials, security, queue mode, task runners and more.
The areas you touch most:
- Database — switching to PostgreSQL
- Endpoints — the externally visible address used in webhook URLs; get this wrong and webhooks advertise the wrong address
- Executions — which executions are saved and for how long
- Binary data — whether large files are held in memory or on the filesystem
- Nodes — disabling certain nodes entirely (those with disk access, for instance)
The encryption key deserves separate attention: by default it is generated on first start, but in production you should set it yourself and manage it as an environment variable. n8n also documents a procedure for rotating it.
| Mode | How it works | When you need it |
|---|---|---|
| Single instance (main) | One n8n process both listens for triggers and executes | Small to medium load — enough for most teams |
| Queue mode | The main instance receives triggers and puts executions on a Redis queue; workers pick them up and run them | High load, parallel execution, scaling by adding or removing workers |
An important queue-mode limitation: it does not support filesystem binary data storage. If your workflows must persist binary data in queue mode, you need external storage such as S3. That forces the architectural decision up front.
The flow in queue mode is:
1. The main instance handles timers and webhook calls and creates an execution — but does not run it 2. It passes the execution ID to Redis, which holds the queue of pending executions 3. An available worker picks up the message 4. The worker uses the execution ID to fetch the workflow from the database and runs it 5. When finished it writes the result to the database and tells Redis it is done 6. Redis notifies the main instance
Each worker is its own Node.js instance and can handle several executions at once. You add workers to take more load and remove them to take less.
In this setup the encryption key must be identical on every instance — otherwise the workers cannot decrypt credentials.
📚 Sources and documentation
- Self-hosting install optionsofficialdocs.n8n.io
- Install using Docker Composeofficialdocs.n8n.io
- Environment variablesofficialdocs.n8n.io
The full list of configuration variables, grouped by topic.
- Enable queue modeofficialdocs.n8n.io
The main/worker architecture and the binary data limitation, explained officially.
- Rotate encryption keysofficialdocs.n8n.io