We ran self-hosted n8n on a $10 VPS and n8n Cloud side by side for 90 days, executing the same workload on both. This is the writeup we wish existed beforehand — not “which is better” in the abstract, but the actual list of things that were different, so you can decide which differences you can live with.

The dollar math, up front

n8n Cloud Starter Self-hosted (VPS + domain + backups)
Entry cost ~$24/mo, 2.5k executions ~$10/mo, unlimited executions
Our 40k-op workload ~$60-100/mo (Pro tier) ~$10-15/mo (beefier VPS)
Scaling curve Linear, steep Flat until you outgrow the VPS
Sunk setup time 10 minutes One focused afternoon

At our volume, self-hosting saves roughly $500-1,000 a year. That’s real money for a small operation, but it’s not “quit your day job” money — so the decision should rest on the operational differences, not just the spreadsheet. Here they are, honestly.

What Cloud buys you

Updates you never think about. During our 90 days, n8n shipped roughly a dozen releases. Cloud instances updated themselves. Our self-hosted instance needed manual updates, and one of them — a minor version, in fairness — required a database migration step that failed on the first attempt and took an hour to fix. If “an hour of unexpected Docker surgery twice a year” is an unacceptable sentence to you, pay for Cloud.

Infrastructure that’s already monitoring itself. Cloud tells you when executions fail. Self-hosted, the workflow failure notification is your problem — n8n self-hosted doesn’t even send you an email unless you configure an error workflow (do this on day one; our error workflow emails us the workflow name, the failing node, and a link).

SSO and the enterprise niceties. If your organization needs single sign-on, that’s a Cloud/enterprise feature. This alone decides it for some teams, and no amount of VPS savings changes it.

Someone else’s pager. When the VPS provider had a two-hour network blip (it happened once), Cloud was unaffected and our self-hosted instance was simply down. Automations that fail to run don’t send alerts about not running — that’s a monitoring gap you must build yourself.

What self-hosting buys you

Unlimited executions, full stop. No quotas, no overage anxiety, no “will this busy week blow the plan?” The psychological difference is bigger than the financial one. We stopped thinking about execution counts entirely, which changed how we designed workflows — batch jobs that would have been reckless on a metered plan became routine.

Data residency. Everything — credentials, execution logs, customer data flowing through workflows — lives on a server you control, in a jurisdiction you chose. For EU clients with GDPR opinions and anyone with contracts that say “data shall not leave X,” this is the entire decision, made in one line.

The Community edition is the real product. n8n’s fair-code license gives self-hosters the full workflow engine. The gaps versus Cloud are narrow: SSO, log streaming, some LDAP/enterprise features. The automation capability itself is identical — this is not a crippled “free edition” upsell.

No per-user or per-execution surprise. Your cost is a VPS bill: $8-15/month flat. Growth means a slightly bigger VPS, not a pricing-tier negotiation.

Custom nodes and code without limits. Self-hosted instances can load community nodes and custom code more freely. We run two community nodes that Cloud’s Starter tier didn’t include at the time.

The honest operational ledger

90 days of self-hosting, logged:

  • Setup: 3 hours (Docker, reverse proxy, HTTPS via Caddy, Postgres, backup script, error workflow)
  • Updates: 6 sessions, ~30 min average, including the one broken migration
  • Monitoring buildout: 2 hours (uptime checks on the VPS and health endpoint, alerting if the n8n container dies — remember, a dead instance is silent)
  • Incidents: 1 (the VPS network blip; 2 hours of missed executions)
  • Total: roughly 8-10 hours over 90 days, or about 20-30 minutes a month

At freelance rates that labor is worth more than the Cloud savings — so we’re effectively paying ourselves in control and data residency, not in dollars. If your hourly value is high and your compliance needs are low, Cloud is the rational choice. That’s the honest arithmetic.

The setup, reproduced step by step

Since “3 hours of setup” is the number people most want to interrogate, here’s what those 3 hours actually contained on our reference install (a $10/month, 2-core/4GB VPS — the size we’d recommend for most small-business workloads):

  1. VPS + Docker (~30 min). Fresh Ubuntu LTS, install Docker and Docker Compose from the vendor’s own install script. This is the easiest part; every provider has a one-click Ubuntu image.
  2. The compose file (~15 min). One docker-compose.yml with three services: n8n itself, PostgreSQL, and Caddy as the reverse proxy. The n8n docs publish a reference compose file; we used it nearly verbatim, changing the domain, the database password, and the timezone environment variables (GENERIC_TIMEZONE — the setting whose absence causes the “why did my scheduled flow fire at 3am” mystery).
  3. DNS + HTTPS (~10 min). Point an A record at the VPS, and Caddy handles certificates automatically. The first docker compose up -d and a two-minute wait for cert issuance; the instance is live on n8n.yourdomain.com.
  4. The day-one guardrails (~45 min). The error workflow (email on any workflow failure — this is the single most important 30 minutes of self-hosting), the instance owner account, execution-data retention set to 30 days (disk fills faster than you’d expect with default settings on a small VPS), and the timezone check.
  5. Backups (~30 min). A nightly cron: pg_dump the n8n database, tar the Docker volumes, upload to object storage with a 30-day lifecycle policy. Then the step everyone skips: do a test restore on a local Docker instance to confirm the backup actually works. Ours did; the docs claim this is optional. It is not.
  6. Monitoring (~20 min). An external uptime check on the instance URL (any free-tier monitor works) plus a container-level health check that restarts n8n if the process dies. A dead instance is silent — see the ledger above — so this is what makes silence detectable.

Total: 2h40m for us, and we’ve done it several times. Budget 4-5 hours the first time; the gap between those numbers is entirely the Docker concepts that are unfamiliar the first pass (volumes, compose networking, and log inspection — docker compose logs -f n8n is the command you’ll use most in month one).

The upgrade procedure, and the day it bit us

The recurring ~30-minute monthly cost is mostly updates, so here’s the procedure and the one failure we’ve had:

Normal update: docker compose pull && docker compose up -d — new image, database migrations run automatically, two minutes of downtime, done. We’ve run this a dozen times without incident except one.

The exception: a minor version jump required a manual Postgres migration step that the release notes mentioned in one sentence, mid-paragraph. docker compose up -d failed with an error mentioning the database schema version; the fix was a one-command migration the docs’ troubleshooting section did cover, but only after we’d gone looking for it. Total incident: an hour, including the part where we restored from backup to a test instance to make sure we understood the failure before touching production (the test restore from step 5 above — this is why you do it).

Lesson, generalized: read the release notes before pulling, and never update a self-hosted n8n the same week a version ships. Let other people find the sharp edges for a week; they post about them in the community forum, and the forum is a genuinely good resource in a way most products’ aren’t. Pin your compose file to a specific version tag rather than latest — it makes updates a deliberate act instead of something that happens to you the next time you rebuild the container.

The checklist we’d give a friend

Before self-hosting, confirm:

  1. You can run Docker on a VPS and won’t panic when a container exits. Everything else is learnable; this is the floor.
  2. You’ll set up the error workflow on day one. Self-hosted n8n fails silently by default. The 30-minute investment in “email me when anything fails” is the difference between self-hosting being fine and being a hazard.
  3. Backups run automatically. We export workflows and the Postgres volume nightly to object storage. Test the restore once — an untested backup is a rumor.
  4. You have an uptime monitor. Not for n8n specifically — for the VPS itself. See “a dead instance is silent” above.
  5. You actually have a compliance or volume reason. Below ~2,000 executions a month, Cloud’s starter tier is cheap enough that self-hosting’s operational overhead isn’t worth optimizing yet. Revisit at scale.

Our verdict

Pick Cloud if your volume is modest, your time is worth more than the savings, you need SSO, or the phrase “SSH in and check the logs” fills you with dread. The product is identical and updates are someone else’s job.

Pick self-hosted if data residency matters, your volume makes metering expensive, you have basic Docker competence (or curiosity and a weekend), and you’ll actually do the day-one error workflow and backups.

Our own answer: we went self-hosted, for the data residency and the unlimited executions, knowing full well it costs us ~30 minutes a month of labor. We don’t regret it — but we also don’t pretend it’s free. The $10 VPS line item is the small number; the real price is the operational attention, and now you know exactly how much of it to budget.