Skip to content
OneLessTool

Replacement workflow · reviewed Oct 13, 2026

Move simple and medium Zaps to n8n (self-hosted or n8n Cloud)

Inventory your Zaps, stand up n8n Community Edition on a small VPS with Docker Compose (or use n8n Cloud), migrate lowest-risk Zaps first, parallel-run each one, and only then cancel. You trade a per-task bill for owning uptime, patching and backups.

advancedSetup 1 day for the server and…Per run Ongoing: ~1 hour/month f…+$14.4/monthEditorial
Replaces
Zapier(full)
Uses
n8nThe automation engine: self-hosted Community Edition (free under the Sustainable Use License for internal use) or a paid n8n Cloud plan.
Claude (optional)Translates Zap logic into n8n expressions and Code-node JavaScript, and helps read error messages.
ChatGPT (optional)Alternative to Claude for expression/Code-node help.
Google Workspace (optional)Hosts the Zap inventory spreadsheet (any spreadsheet works).
Time
Setup: 1 day for the server and first wave; 2–4 weeks elapsed for all waves including parallel runs
Per run: Ongoing: ~1 hour/month for updates, backup checks and failed-execution review
Extra cost
Self-hosted: a DigitalOcean Basic Droplet with 2 GiB RAM is $12/month and weekly backups add 20% ($2.40), per DigitalOcean's pricing page today — $14.40/month. A 1 GiB droplet is $6 but leaves little headroom (our judgement, not an n8n requirement). Any comparable VPS works. A domain name and your own time are extra. n8n Cloud instead: Starter was listed at €20/month billed annually on n8n's pricing page (shown in euros to us; 2,500 executions/month) — no server to run, but it's a subscription.

Is it for you?

Today

Zaps run on Zapier's cloud. Pricing is per task; multi-step Zaps need a paid plan (Free allows only two-step Zaps and 100 tasks/month). Zapier handles hosting, OAuth app registrations, retries and uptime. You pay more as volume grows.

With this workflow

n8n runs in Docker on a small VPS behind Traefik with automatic HTTPS, or on n8n Cloud. Each Zap is rebuilt as an n8n workflow, parallel-run against the original, then switched over. An Error Workflow alerts you on failures, nightly exports plus volume snapshots back everything up, and Zapier is downgraded to Free (for any leftovers) or cancelled after 30 quiet days.

Good fit if…

  • Teams paying for Zapier Pro/Team mainly because of task volume or multi-step Zaps
  • Someone on the team comfortable with Linux, Docker, DNS and reading logs
  • Automations between mainstream apps that have native n8n nodes or simple REST APIs
  • Organisations that want automation data to stay on infrastructure they control

Not for you if…

  • No one technical to own updates, security patches, backups and 2 a.m. failures — stay on Zapier or use n8n Cloud
  • Mission-critical automations (billing, customer-facing messages, compliance) without monitoring and alerting in place
  • Zaps built on Zapier-only features (Zapier Tables, Interfaces, Chatbots) or niche apps with no n8n node and no usable API
  • Offering automation to your own customers (letting clients build or edit workflows) — not allowed under n8n's Sustainable Use License without a commercial agreement

Step by step

  1. 1

    Inventory every Zap and assign migration waves

    Fill the Zap inventory artifact: one row per Zap, including disabled ones you might need.

    • Pull tasks used in the last 30 days from Zapier's task history so you know real volume.
    • Mark anything using Zapier Tables, Interfaces, Chatbots, Email Parser or apps with no n8n node — these need redesign, not migration.
    • Assign waves (1 = internal, low-impact, ≤3 steps → 4 = needs redesign).

    If most of your task volume sits in wave 4, stop here: the migration may cost more than it saves.

  2. 2

    Choose hosting and check the license

    Self-hosted Community Edition is free under n8n's Sustainable Use License when only you or people in your organisation build workflows. Running your own business on it, building automations for clients on your instance (clients can't edit them) and charging for setup/consulting are allowed. Not allowed: hosting n8n as a service where clients build workflows, white-labelling, or using license-key enterprise features without a license. Read n8n's license FAQ if you're an agency.

    n8n Cloud removes server work; its pricing page listed Starter at €20/month billed annually with 2,500 executions (prices shown in euros to us — check yours). Note that n8n counts executions (one per workflow run) rather than Zapier's per-action tasks, so compare volumes carefully.

    For self-hosting, a 2 GiB RAM VPS is a comfortable start for a few dozen low-volume workflows (our judgement).

  3. 3

    Deploy n8n with Docker Compose

    On a fresh Ubuntu VPS with Docker installed:

    1. Create an A record n8n.yourdomain.com → server IP.
    2. Firewall: allow 22 (ideally only from your IP), 80 and 443; nothing else.
    3. Save the docker-compose.yml artifact and its .env block. Generate the key with openssl rand -hex 32 and store it in your password manager — lose it and every stored credential is unreadable.
    4. mkdir -p local-files backups && docker compose up -d, then open https://n8n.yourdomain.com and create the owner account immediately. Since n8n 1.0 there are no N8N_BASIC_AUTH_* variables; the owner login is the protection.
    5. Turn on 2FA for the owner (Settings → Personal → Enable 2FA), and turn on your VPS provider's backups.

    Check N8N_WEBHOOK_URL vs WEBHOOK_URL against your pinned version (the docs say N8N_WEBHOOK_URL needs 2.30.0+); if webhook URLs in the editor show localhost, you used the wrong one.

  4. 4

    Set up credentials, backups and failure alerts before migrating anything

    • Credentials: for Google, Microsoft, Slack and similar OAuth apps on self-hosted n8n, you usually register your own OAuth app in that vendor's developer console and paste in the redirect URL n8n shows. Budget time for Google's consent-screen setup. API-key apps (Stripe, Typeform, Airtable) are quicker.
    • Error Workflow: build one workflow that starts with an Error Trigger and sends email/Slack with the workflow name and execution URL. Select it under each workflow's Settings → Error workflow.
    • Backups: nightly cron on the host:
      • docker compose exec -u node n8n n8n export:workflow --backup --output=/backups/workflows/
      • docker compose exec -u node n8n n8n export:credentials --backup --output=/backups/credentials/ (still encrypted — restore needs the same N8N_ENCRYPTION_KEY)
      • copy ./backups off the server (e.g. rclone to cloud storage) and keep the .env in your password manager.
    • Test a restore onto a scratch server once. A backup you haven't restored is a hope, not a backup.
  5. 5

    Rebuild Zaps wave by wave

    For each Zap, screenshot every step, then rebuild in n8n. Rough mapping:

    Zapier n8n
    Trigger app App trigger node, Webhook node, or Schedule Trigger + poll
    Filter If / Filter node
    Paths Switch node
    Formatter Edit Fields (Set) with expressions, or Code node
    Delay Wait node
    Looping items flow through nodes automatically; Loop Over Items for batches
    Webhooks by Zapier Webhook / HTTP Request nodes

    Paste the Zap's step list into the Translate a Zap into an n8n workflow plan prompt to get a node-by-node plan and expressions. Expressions use {{ $json.field }} syntax — the most common bug is referencing data from the wrong node.

  6. 6

    Parallel-run, switch over, then downgrade Zapier

    Follow the Cutover checklist for every Zap: at least 7 days or 20 executions side by side, matching counts between Zapier task history and n8n's Executions list, and a field-level diff on 5 runs (time zones and date formats are the usual culprits).

    For actions that must not happen twice (payments, customer emails), never run both live — replay recent payloads into n8n with the last step disabled.

    Switch by activating the n8n workflow and turning the Zap off in the same minute; re-point any third-party webhooks. Keep turned-off Zaps for 30 days. Then move leftovers to Zapier Free if they fit (two-step, ≤100 tasks/month) or cancel.

Prompts you can use now

Copy as-is, or fill in the blanks first. Highlighted parts are placeholders.

Translate a Zap into an n8n workflow plan

Get a node-by-node rebuild plan with expressions from a Zap description.

Fill in 3 blanks (optional)
I'm migrating a Zapier Zap to n8n (version {{n8n_version}}, self-hosted). Here is the Zap, step by step, including field mappings, filters and formatter settings:

{{zap_steps}}

Sample trigger payload (JSON, sensitive values redacted):
{{sample_payload}}

Give me:
1. A numbered list of n8n nodes (exact node names as they appear in n8n), with the settings to choose in each.
2. Every expression I need, in n8n syntax (e.g. {{ $json.email }} or {{ $('Node Name').item.json.field }}), mapped to the original Zap field.
3. Anything in this Zap with no direct n8n equivalent and how to handle it (HTTP Request node, Code node, or redesign).
4. Time zone, date-format and empty-field pitfalls specific to this Zap.
5. A test plan: which 3 sample inputs prove the n8n version matches the Zap.
If you're unsure whether a node or option exists in this n8n version, say so rather than inventing it.

Write an n8n Code node

Replace Zapier Formatter/Code steps with a tested Code node.

Fill in 4 blanks (optional)
Write JavaScript for an n8n Code node in mode "{{code_mode}}" ("Run Once for All Items" or "Run Once for Each Item").

Input items look like this (JSON):
{{input_example}}

Output items must look like this:
{{output_example}}

Transformation rules:
{{rules}}

Requirements: use $input.all() or $input.item as appropriate for the mode; return items in n8n's [{ json: {...} }] shape; no external npm packages; handle missing fields without throwing; add short comments. Then give two edge-case inputs and the expected outputs so I can test it.

Diagnose a failed n8n execution

Turn an n8n error into a fix during parallel running.

Fill in 5 blanks (optional)
An n8n workflow failed during a parallel run against the original Zap.

Node that failed: {{node_name}} ({{node_type}})
Error message: {{error_message}}
Input data to that node (redacted): {{node_input}}
What the Zapier version produced for the same trigger: {{zapier_output}}

Explain the most likely cause in plain English, give the exact fix (setting, expression or credential change), and tell me how to confirm it's fixed without triggering real side-effects (emails, payments, CRM writes).

Templates, scripts & configs

docker-compose.yml + .env for n8n behind Traefik (HTTPS)

config · yaml

# docker-compose.yml — n8n Community Edition behind Traefik (automatic HTTPS)
# Adapted from n8n's "Docker Compose" server-setup guide (docs.n8n.io, checked 2026-10-13).
# Changes from the docs example: pinned image tag, explicit N8N_ENCRYPTION_KEY,
# Traefik dashboard NOT exposed (the docs example sets --api.insecure=true).
#
# Login: n8n has NO basic-auth env vars any more — N8N_BASIC_AUTH_* were removed in n8n 1.0.
# Access is protected by n8n's own user management: the first visitor creates the OWNER account.
# So create the owner account immediately after first start (or firewall port 443 to your IP until you have).

services:
  traefik:
    image: "traefik:${TRAEFIK_VERSION}"
    restart: always
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
      - "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
      - "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - traefik_data:/letsencrypt
      - /var/run/docker.sock:/var/run/docker.sock:ro

  n8n:
    image: "n8nio/n8n:${N8N_VERSION}"     # pin a version; upgrade deliberately after reading release notes
    restart: always
    ports:
      - "127.0.0.1:5678:5678"             # only reachable through Traefik, not directly from the internet
    labels:
      - traefik.enable=true
      - traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)
      - traefik.http.routers.n8n.tls=true
      - traefik.http.routers.n8n.entrypoints=web,websecure
      - traefik.http.routers.n8n.tls.certresolver=mytlschallenge
      - traefik.http.middlewares.n8n.headers.SSLRedirect=true
      - traefik.http.middlewares.n8n.headers.STSSeconds=315360000
      - traefik.http.middlewares.n8n.headers.browserXSSFilter=true
      - traefik.http.middlewares.n8n.headers.contentTypeNosniff=true
      - traefik.http.middlewares.n8n.headers.forceSTSHeader=true
      - traefik.http.middlewares.n8n.headers.SSLHost=${DOMAIN_NAME}
      - traefik.http.middlewares.n8n.headers.STSIncludeSubdomains=true
      - traefik.http.middlewares.n8n.headers.STSPreload=true
      - traefik.http.routers.n8n.middlewares=n8n@docker
    environment:
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}   # encrypts stored credentials; back this up separately
      - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
      - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - N8N_WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/  # n8n >= 2.30.0
      # - WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/    # use this name instead on n8n < 2.30.0
      - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}                   # used by Schedule Trigger
      - TZ=${GENERIC_TIMEZONE}
      - N8N_RESTRICT_FILE_ACCESS_TO=/files
    volumes:
      - n8n_data:/home/node/.n8n      # SQLite database, encryption key, settings — THIS is what you back up
      - ./local-files:/files          # create this folder yourself before first start
      - ./backups:/backups            # target for `n8n export:*` backup commands

volumes:
  n8n_data:
  traefik_data:

# ---------------------------------------------------------------------------
# .env  (same folder; chmod 600 .env; never commit it)
# ---------------------------------------------------------------------------
# DOMAIN_NAME=example.com
# SUBDOMAIN=n8n                       # → https://n8n.example.com  (create an A record to the server IP)
# GENERIC_TIMEZONE=America/New_York
# SSL_EMAIL=you@example.com           # Let's Encrypt contact
# N8N_VERSION=<current stable tag from n8n release notes, e.g. 2.x.y>
# TRAEFIK_VERSION=<current stable v3 tag>
# N8N_ENCRYPTION_KEY=<output of: openssl rand -hex 32>
#
# Start:    mkdir -p local-files backups && docker compose up -d
# Update:   edit N8N_VERSION, then: docker compose pull && docker compose down && docker compose up -d
# Logs:     docker compose logs -f n8n
#
# Bigger installs: n8n's n8n-hosting repository has a PostgreSQL compose example.
# SQLite (the default above) is fine for a few dozen low-volume workflows.

Zap inventory spreadsheet template

template

ZAP INVENTORY — one row per Zap (Google Sheets / Excel). Export the list from Zapier's Zaps page, then fill in by hand.

Columns:
| Zap name | Zapier folder | Owner | On/Off | Trigger app + event | Action steps (apps, in order) | Steps count | Uses Filter/Paths/Formatter/Code? | Uses Zapier-only apps (Tables, Interfaces, Chatbots, Email Parser)? | Tasks last 30 days | Business impact if it fails (Low/Med/High) | Has a premium/partner app? | n8n node exists for every app? (Y/N/HTTP) | Auth type needed (OAuth/API key) | Migration wave (1–4) | n8n workflow name | Parallel-run start | Parallel-run result | Zap turned off on | Notes |

Example rows:
| New Typeform → Sheets row + Slack | Marketing | Ana | On | Typeform: New Entry | Google Sheets: Append; Slack: Send message | 3 | No | No | 120 | Low | No | Y | OAuth (Google, Slack), API key (Typeform) | 1 | MKT – Typeform to Sheets | 2026-10-20 | 120/120 matched | 2026-10-27 | |
| Stripe paid → invoice email + CRM deal | Finance | Sam | On | Stripe: New Payment | Formatter; HubSpot: Update deal; Gmail: Send | 4 | Formatter | No | 85 | High | No | Y | API key (Stripe), OAuth (HubSpot, Gmail) | 3 | FIN – Stripe payment sync | | | | wait for monitoring |
| Daily digest via Zapier Tables | Ops | Lee | On | Schedule | Zapier Tables: Find; Digest | 3 | No | YES | 30 | Med | No | N | — | 4 | | | | | needs redesign: move table to Sheets first |

WAVES (lowest risk first):
  1 = internal-only, Low impact, ≤3 steps, all apps have native n8n nodes (notifications, logging to Sheets)
  2 = Medium impact or uses filters/formatting, still native nodes
  3 = High impact (money, customers, CRM) or webhooks from third parties — migrate only after error alerts work
  4 = uses Zapier-only features or apps with no n8n node → redesign, use HTTP Request node, or keep on Zapier Free

Per-Zap cutover checklist (parallel run → switch → downgrade)

checklist

CUTOVER CHECKLIST — per Zap

Before building
[ ] Row filled in the inventory, wave assigned
[ ] Credentials created in n8n (Credentials → Add). For Google/Microsoft OAuth on self-hosted n8n you
    register your own OAuth app and paste the redirect URL n8n shows you — allow 30–60 min the first time.

Build
[ ] Same trigger, same filters, same field mappings (screenshot each Zap step for reference)
[ ] Workflow name = "<TEAM> – <what it does>"; description says which Zap it replaces
[ ] Error handling: an Error Workflow is set in workflow Settings that alerts email/Slack on failure

Parallel run (minimum 7 days or 20 executions, whichever is longer)
[ ] For triggers that can safely run twice: run both, but point n8n's final action at a TEST destination
    (test Slack channel, test sheet tab) and compare outputs daily
[ ] For actions that must not double-fire (payments, customer emails, CRM updates): replay the last
    20 real trigger payloads into n8n with the final step disabled; compare the data each step would send
[ ] Compare counts: Zapier task history vs n8n Executions list — every Zapier run has a matching n8n run
[ ] Field-level diff on at least 5 runs (dates, time zones, number formats, empty fields)

Switch
[ ] Point n8n's final step at production, activate the workflow, turn the Zap OFF in the same minute
[ ] Re-point any third-party webhooks from the Zapier URL to the n8n production webhook URL
[ ] Watch the first 24 h of executions; keep the Zap (off) for 30 days for rollback

After all waves
[ ] Backups proven by a test restore onto a scratch server
[ ] Uptime monitor on https://<your-n8n>/healthz/readiness (returns 200 only when n8n and its database are ready)
[ ] Zapier downgraded to Free (or cancelled) only after 30 days without rollback

What you give up

  • Fewer integrations than Zapier; niche apps may need the HTTP Request node and the vendor's API docs.
  • On self-hosted n8n you register your own OAuth apps for Google, Microsoft and others — slower first-time setup and occasional re-verification work.
  • No Zapier-only features: Zapier Tables, Interfaces and Chatbots must be redesigned (e.g. Sheets/Airtable plus n8n forms).
  • Billing units differ: n8n Cloud counts executions (workflow runs), Zapier counts tasks (actions), so plan comparisons aren't one-to-one.
  • SQLite (the default) suits small installs; heavy volume or queue mode needs PostgreSQL and more ops work.
  • Your automations stop when your server stops: there's no vendor SLA on self-hosted Community Edition.

Risks

  • highreliability

    You own uptime. A full disk, expired certificate or failed upgrade silently stops every automation. Mitigate with an uptime monitor, an Error Workflow and pinned versions upgraded deliberately.

  • highsecurity

    An internet-facing n8n holds API keys and OAuth tokens for your core apps. Patch promptly (n8n has had security advisories), create the owner account immediately, enable 2FA, keep port 5678 bound to localhost, and don't expose the Traefik dashboard.

  • mediumdata portability

    Losing N8N_ENCRYPTION_KEY makes stored credentials unrecoverable. Back up the key separately from the data, and test a restore.

  • mediumip licensing

    The Sustainable Use License permits internal business use but not hosting n8n as a service where clients build workflows, white-labelling, or using enterprise features without a license key.

  • mediummigration complexity

    Subtle differences (time zones, date formats, how empty fields and arrays are handled) cause wrong-but-successful runs. Parallel runs with field-level diffs catch most of them.

Before you cancel

Run these in parallel with your current tool. Only cancel when every box is ticked.

0/8 checks passed

Saved in this browser only. Cancel the old subscription only after every check passes.

How the savings work

Savings = current Zapier monthly bill − (VPS + backups) for self-hosting, or − n8n Cloud plan. Use the Zapier plan you'd actually need for your task volume (check task history). We don't convert your admin time into dollars; at ~1 hour/month after setup plus 1–3 days of migration effort, include it if your time is expensive. If some Zaps must stay, subtract the Zapier plan you'll keep (Free is $0 for two-step Zaps up to 100 tasks/month).

Example

A 6-person company on Zapier Pro (2,000 tasks/month tier, monthly billing) with 15 multi-step Zaps, all on mainstream apps, moving to self-hosted n8n.

Before$73.50/mo
After$14.40/mo
Saving$59.10/mo · $709/yr
  • Zapier Pro at the 2,000 tasks/month tier is $73.50/month billed monthly ($49.00/month billed annually), per zapier.com/pricing on 2026-10-13.
  • Self-hosting on a DigitalOcean 2 GiB Basic Droplet ($12/month) with weekly backups (+20% = $2.40), per digitalocean.com/pricing/droplets on 2026-10-13.
  • All 15 Zaps use apps with native n8n nodes; none rely on Zapier Tables/Interfaces, so Zapier is cancelled rather than kept on Free.
  • Domain name already owned; admin time not priced. On annual Zapier billing the saving would be $49.00 − $14.40 = $34.60/month.

Personalise this workflow

Tailors the steps and prompts to your tools, team and volume using only our verified catalog data.

Tools you already pay for

Sources & freshness

  1. n8n docs — Docker Compose server setup — accessed Oct 13, 2026 · Compose example with Traefik; env vars N8N_HOST, N8N_PORT, N8N_PROTOCOL, NODE_ENV, N8N_WEBHOOK_URL (2.30.0+, WEBHOOK_URL before), GENERIC_TIMEZONE, TZ, N8N_RESTRICT_FILE_ACCESS_TO, N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS; n8n_data volume at /home/node/.n8n.
  2. n8n docs — Docker installation — accessed Oct 13, 2026 · Image n8nio/n8n; persistence at /home/node/.n8n; update via docker compose pull/down/up.
  3. n8n docs — deployment environment variables — accessed Oct 13, 2026 · N8N_ENCRYPTION_KEY encrypts credentials in the database; random key generated on first launch if unset.
  4. n8n docs — CLI commands — accessed Oct 13, 2026 · export:workflow/export:credentials with --backup; import with --separate; docker exec -u node usage.
  5. n8n license FAQ (Sustainable Use License) — accessed Oct 13, 2026 · Free for internal use; not allowed: hosting as a service where clients build workflows, white-labelling, enterprise features without license.
  6. n8n 1.0 migration guide — accessed Oct 13, 2026 · User management mandatory; BasicAuth and External JWT authentication removed.
  7. n8n docs — Monitor n8n — accessed Oct 13, 2026 · /healthz returns 200 when reachable; /healthz/readiness adds the database check.
  8. n8n docs — Two-factor authentication — accessed Oct 13, 2026 · Users enable 2FA under Settings > Personal with an authenticator app.
  9. n8n pricing — accessed Oct 13, 2026 · Cloud Starter €20/mo billed annually, 2,500 executions; Pro €50/mo, 10,000 executions (shown in EUR to our fetch).
  10. Zapier pricing — accessed Oct 13, 2026 · Free: 100 tasks, two-step Zaps only. Pro 750 tasks $29.99 monthly/$19.99 annual; 2,000 tasks $73.50 monthly/$49.00 annual.
  11. DigitalOcean Droplet pricing — accessed Oct 13, 2026 · Basic: $6/mo 1 GiB, $12/mo 2 GiB; weekly backups 20% of Droplet cost.

Evidence: editorial — Compose file adapted from n8n's documented example on 2026-10-13 (pinned tags, explicit encryption key, Traefik dashboard removed). VPS sizing is editorial judgement. n8n's docs do not specify minimum hardware on the pages checked. · Machine-readable: JSON · Markdown