n8n runs in ten minutes with Docker. That is exactly the problem. The quick start lives on a single VM, with SQLite, without backups, and six months later your invoice runs depend on it. We run n8n for clients on AWS. Here is what a setup needs so that IT lead, data protection officer and works council all sign off on it.
Why self-host at all
The question comes up in every project. In our experience, three reasons speak for self-hosting:
- GDPR and data processing agreements: the data stays in your AWS account in Frankfurt. You do not need another processor for the automation platform, and you enforce retention periods yourself.
- Banking data and payments: if you process account transactions, dunning runs or SEPA files, you do not want execution data sitting with a third party. In an audit, "it runs inside our VPC" is a short answer.
- Works council: workflows often touch employee data, for example in onboarding or time tracking. A works agreement is easier when you control access, logging and retention yourself.
The same applies when you use Claude inside the workflows. You decide which fields go to the model and which are masked beforehand. On top of that, self-hosting has no execution limits. A nightly reconciliation over many thousands of records costs compute, not licence.
Queue mode: one process is not enough
By default n8n does everything in one process: UI, webhooks, triggers and executions. That is fine for experiments. Once a long workflow blocks the UI or a restart kills running executions, it stops being fine.
The enterprise setup uses queue mode:
- One main process serves the UI and the triggers.
- Dedicated webhook processes accept incoming calls, even when the workers are under load.
- Workers execute the workflows. They scale horizontally, in our setups usually as containers on ECS Fargate.
- Redis on ElastiCache distributes the jobs.
- Postgres on RDS stores workflows, credentials and executions. SQLite has no place in production.
The core configuration is manageable:
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=<elasticache-endpoint>
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=<rds-endpoint>
N8N_ENCRYPTION_KEY=<from Secrets Manager>
EXECUTIONS_DATA_PRUNE=true
EXECUTIONS_DATA_MAX_AGE=336
The last two lines are easily forgotten. Without pruning, the executions table grows until RDS slows down. For financial data, agree the retention period with the business unit, not with the default.
Access: SSO and secrets
Local n8n users with passwords stop being manageable at ten people. Two things belong in the setup:
- SSO via SAML or OIDC, connected to Entra ID or Okta. When someone leaves the company, access ends centrally. SAML and OIDC are only available in n8n with an Enterprise licence. Without the licence, we put the Application Load Balancer with OIDC authentication in front of the UI. Webhooks stay reachable on their own path.
- Secrets do not belong in plain text in the task definition. ECS reads them directly from AWS Secrets Manager. The most important one is
N8N_ENCRYPTION_KEY: lose it and every stored credential is worthless. So it goes into Secrets Manager, without automatic rotation, with access logging via CloudTrail.
Add projects and roles in n8n: separate finance workflows from marketing workflows. Someone who cannot see a credential cannot accidentally use it in a test workflow.
Backups and updates without downtime
Backups have two parts. First, automated RDS snapshots with point-in-time recovery. Second, a nightly export of all workflows as JSON into a versioned S3 bucket, via the n8n API. That is your audit trail: who changed which workflow and when. And test the restore once a quarter in a separate environment. A backup that has never been restored is an assumption.
n8n releases weekly. Not every version needs to go to production. Our approach:
- Pin versions, never
latest. - Staging first, with a smoke test of the critical workflows.
- Rolling deployment on ECS: new workers start, old workers finish their current jobs and then stop. The container has to handle SIGTERM cleanly, and n8n supports that.
- The main process runs database migrations at startup. The UI is briefly unavailable during that time. Webhooks and workers keep running, and that is the part that matters.
Monitoring in CloudWatch
A workflow that dies quietly is only noticed when accounting asks. So:
- Container logs go to CloudWatch Logs as JSON with
N8N_LOG_OUTPUT=json, so you can filter by workflow ID. - Metrics come from the
/metricsendpoint in Prometheus format, collected by the CloudWatch agent. Queue length, error rate and duration are the ones that matter. - Alarms on waiting jobs above a threshold, worker restarts, free RDS storage and failed executions per hour.
- Load balancer health check on
/healthz.
If workflows call Claude, for example to extract data from PDF invoices, log token usage and response time as well. Those are cost and latency you want to see. Alarms go to Slack or Teams, to a person who owns the workflow. Error handling inside the workflows themselves is the topic of our next article.
When n8n Cloud is enough
Not every company needs all of this. n8n Cloud is the right choice when:
- no banking, health or employee data runs through the workflows,
- the data processing agreement with n8n satisfies your data protection officer,
- you have no team that runs AWS and no plan to build one,
- your load stays below the execution limits of the plan.
Then you skip the infrastructure and get updates for free. Our honest recommendation: start with Cloud if the data allows it, and migrate later. Workflows are JSON, the move is doable.
Takeaway
A production n8n setup on AWS is not rocket science, but it is also not a Docker one-liner. Queue mode, Postgres, SSO, Secrets Manager, tested backups and alarms are the minimum. We have built this several times and know the traps. If you want to find out whether self-hosting or Cloud fits your case, book a free 30-minute intro call.