Updated: 2026-07-07

n8n is the low-code automation platform that has grown most in the self-hosted world over the last two years. It offers a serious alternative to Zapier and Make for organizations wanting to control their own flows without paying per-integration fees, and it does so with a reasonable visual interface and a licensing model that is permissive for internal use. This article covers the concrete install with Docker Compose, the architecture decisions to make at start, and the points where most people stumble the first time.

Key takeaways

  • The first important decision is the database: start directly with PostgreSQL, not SQLite, for any deployment with more than one flow or user.

  • Queue mode (separating web process from workers via Redis) is needed above five frequently-executed flows.

  • N8N_ENCRYPTION_KEY is the most critical variable: generate it once, store it safely, and never change it.

  • Public webhooks require WEBHOOK_URL to point exactly to the public domain reachable from the internet, not localhost.

  • /home/node/.n8n persistence must go on a named volume; several teams have lost flows and credentials by forgetting this.

What n8n does and when self-hosting makes sense

n8n lets you connect tools via visual flows where each node is an action, a trigger, or a transformation. There are nodes for hundreds of common services: Google Workspace, Slack, databases, generic HTTP APIs, message queues, WhatsApp, email, object storage. When a node doesn’t exist, a code node allows writing JavaScript or Python for almost anything.

The project’s source is available from its main GitHub repository[1], with the official image published on Docker Hub[2]. Since 2022 it has shipped under the Sustainable Use License, a fair-code model that lets you use and modify the code freely for internal or non-commercial use, but restricts reselling it as a competing service (license details[3]).

Self-hosting makes sense for three main reasons:

  • Sensitive data control: if your flows move customer data, contracts, or financial data, having them bouncing between external SaaS and internal systems is an exposure not all organizations accept.

  • Cost: the self-hosted version doesn’t charge per flow execution, which for high volumes is a substantial saving.

  • Flexibility: integrating with internal systems, private APIs, or local databases is much easier when n8n runs inside the same network.

Where it doesn’t make sense is when flows are few and simple, with few external integrations and low volume. In that scenario, the operational friction of maintaining another piece of infrastructure outweighs cost savings.

Database choice

The first decision at install time is the database that stores flows, credentials, execution history, and users. n8n supports SQLite, PostgreSQL, and MySQL. The default is SQLite, which works fine for small single-process installs with few flows.

The recommendation, for almost any deployment with more than one flow or user, is to start directly with PostgreSQL. The official n8n documentation[4] recommends PostgreSQL 13 or later once queue mode is enabled. Migrating from SQLite to PostgreSQL later is possible but awkward, and PostgreSQL advantages appear even at small scales: better backups, clearer introspection, and the ability to enable queue mode later without remigrating.

If you already run a shared PostgreSQL instance, you can use it by creating a dedicated database for n8n, which cuts down the number of containers and simplifies backups. Anyone already managing that Postgres with Docker Compose can lean on the Docker Compose install guide for Ubuntu 20.04 to define both services in the same stack.

Queue mode for serious loads

By default, n8n executes flows in the same process serving the web interface. This mode is fine for low volumes, but with long or many simultaneous flows, problems appear: the interface slows down, executions can block, and horizontal scaling is impossible.

The solution is queue mode, described in the official queue-mode configuration guide[4], which separates the web process from the worker process and connects them through a Redis queue. In this mode the interface stays fast even under load, and you can add more workers to process more flows in parallel.

Configuration consists of defining two Docker services with the same image but different variables:

  • The main one with EXECUTIONS_MODE=queue and QUEUE_BULL_REDIS_HOST pointing at Redis.

  • The workers with the n8n worker command.

The recommendation is that once you pass five frequently-executed flows, you switch to queue mode directly. The operational cost of adding Redis is minimal and avoids an awkward migration once load grows.

Critical environment variables

There are a handful of environment variables worth configuring correctly from the start:

  • N8N_ENCRYPTION_KEY: the key used to encrypt credentials in the database. If this key changes, all stored credentials become unusable. Generate it once with openssl rand -hex 32, save it safely, and never change it.

  • N8N_HOST and WEBHOOK_URL: tell n8n which domain it is accessed from and under which URL public webhooks should be generated. If these don’t match reality, external webhooks will not work. The typical mistake is installing n8n behind Traefik with a domain and forgetting to update WEBHOOK_URL, leaving webhooks pointing at localhost.

  • N8N_RUNNERS_ENABLED: turns on the isolated executor for user code. From recent versions this is the recommended default for any deployment running untrusted code.

Traefik or Nginx in front

In most self-hosted installs, n8n runs behind a proxy like Traefik or Nginx to handle HTTPS and to serve more than one service on the same server. The proxy config is standard: a router pointing at port 5678 on the n8n container, with automatic TLS. Anyone who hasn’t set up the proxy yet can follow the Traefik with Docker Compose install guide, which uses the same Docker Compose syntax[5] as this article.

One detail worth watching is the proxy timeout. Some flows can take minutes to run, especially if they call slow external APIs or process large files. Nginx’s default 60-second timeout can cut these executions short, producing 504 Gateway Timeout errors. Raise it to several minutes for the flow execution routes.

For public webhooks, pay attention to the public URL being reachable from the internet. A common mistake is running n8n on an internal network behind a VPN, adding a webhook to a flow, and not understanding why it never arrives: the external service can’t reach the URL n8n generates.

Typical friction points

Three problems almost everyone hits the first time:

  • Data persistence: the n8n container stores data at /home/node/.n8n, which must go on a persistent volume. Several teams have lost flows and credentials by running docker compose down with the flag that removes volumes. The recommendation is to use named volumes and keep regular database backups.

  • Credential handling: n8n encrypts credentials with N8N_ENCRYPTION_KEY, but the backup process must include both the database and the encryption key. If you restore the database on another server with a different key, all credentials become useless. Always keep both pieces together.

  • Active vs. inactive flows: a flow created but not activated does not run, even though it’s visible in the interface and can be tested manually. The toggle sits at the top of the editor, and it’s worth reviewing the list of active flows after importing or modifying several at once.

Frequently asked questions

Is n8n free to use for myself?

Yes. Under the Sustainable Use License you can use, modify, and self-host n8n at no cost for internal or personal use; what the license restricts is reselling it as a competing SaaS service.

When should I switch on queue mode?

As soon as you go past five frequently-executed flows, or when you notice the interface slowing down under load. The cost of adding Redis is low compared with the awkward migration of doing it later with production data.

What happens if I lose the encryption key?

Every credential stored in the database becomes unusable and has to be re-entered one by one. That’s why N8N_ENCRYPTION_KEY must be backed up alongside the database, never separately.

My take

n8n delivers on its promise: complex automations without writing much code, with control over your data and no per-execution fees. For organizations with between twenty and several hundred flows that want to keep their data in-house, the self-hosted version is competitive against any commercial alternative.

The concrete recommendation is that if you’re evaluating Zapier or Make for serious use in your organization, look at self-hosted n8n before deciding. The monthly infrastructure cost for an install handling the kind of volume you’d pay 100 € for on Zapier tends to sit around 20 €, with the added benefit of integrating with internal systems without friction.

Where it’s worth stopping to think is the opposite case: if you don’t have internal operations with many integrations or sensitive data, and you only need to glue together three common external APIs, the commercial SaaS version is still easier to manage. Self-hosting infrastructure always carries an operational cost, and that cost needs to be justified by real benefit. n8n is no exception to that general rule.

Conclusion

The decision to self-host n8n comes down to one question: does control over data and savings on executions justify the operational cost of maintaining another piece of infrastructure? For medium volumes and sensitive data, the answer is usually yes.

Sources

  1. main GitHub repository
  2. Docker Hub
  3. license details
  4. official n8n documentation
  5. Docker Compose syntax