How I migrated my law firm's intake from Zapier to n8n in 6 weeks
Vasquez Law Firm started with Zapier the way most small firms start with Zapier — one workflow that mattered, then five, then thirty, then suddenly we couldn't change anything without breaking something. By the time we were running 60+ Zaps coordinating CallRail, GoHighLevel, Clio, our forms, and our payment system, the bill was steep, the debugging was frustrating, and a missed conditional in one zap had taken down lead delivery for six hours overnight. We migrated to n8n self-hosted in 6 weeks. This is the playbook.
Why Zapier was the right starting point — and the wrong endpoint
Zapier is genuinely good at what it does. For a one-attorney firm wiring up a single intake form to a single CRM, you can be live in an afternoon, and the per-task pricing is fine. The problems start when your workflows develop branching logic. Each branch in a Zap is roughly its own zap. Each conditional is a 'paths' module that adds a task. Each retry costs tasks. We had a single 'qualified lead' workflow that, by the end, ran through 11 conditionals and called 4 external APIs. Cost ran to several hundred dollars a month for that one workflow alone, and it was fragile — changing one branch often required rewiring two others.
Debugging was the tipping point. When something broke at 2am, we'd find out the next morning from a missing matter in Clio. Zapier's history view tells you a zap failed; it doesn't always tell you why in a way that maps cleanly to the conditional logic. Reconstructing what input arrived and what branch ran took 20-30 minutes per incident. We were doing this 2-3 times a week.
Why n8n specifically
We considered three options: stay on Zapier, move to Make.com, or move to self-hosted n8n. Make is the closest middle ground — visual workflow builder, more debuggable than Zapier, similar SaaS pricing model. We chose n8n self-hosted for two reasons. First: full visibility into the workflow execution log, including the actual inputs and outputs at every node. Second: no per-task pricing — once the n8n instance is up, additional workflow runs are free at the margin. Our task volume was high enough that the math favored self-hosted within 6 months.
The trade-off is operational overhead. n8n self-hosted needs a server, monitoring, backups, and someone who knows what to do when it goes down. We use a managed deployment (Docker on a Hetzner VPS, with PostgreSQL backed up nightly to S3), which keeps the operational load light but doesn't eliminate it. If you don't have anyone on the team comfortable with that, n8n Cloud or Make.com is probably the better answer.
The migration plan that worked
We didn't do a big-bang migration. We classified the 60+ Zaps into three buckets: (1) high-stakes, business-critical workflows like inbound lead delivery — those got migrated and run in parallel for 2 weeks before Zapier was turned off; (2) medium-stakes workflows like contract follow-up sequences — migrated one at a time with a 3-day parallel run; (3) low-stakes utility zaps like 'send me a Slack message when X happens' — migrated last, no parallel run.
The parallel-run discipline was the most important thing we did. For 2 weeks, every inbound call generated both a Zapier run and an n8n run, and we manually compared the outcomes. We caught 4 cases where the n8n logic produced subtly different results than Zapier — usually because Zapier had quietly handled a null value as an empty string and n8n was treating it as a real null. Without the parallel run, we'd have shipped those bugs into production and only found them when downstream Clio matters started showing missing fields.
- ✓Classify workflows by stakes; migrate high-stakes first with parallel run
- ✓Run old + new systems in parallel and compare outcomes manually for 1-2 weeks
- ✓Don't trust your assumptions about how the old system handled edge cases
- ✓Keep a rollback plan for every workflow during the cutover window
- ✓Migrate utility/low-stakes workflows last, no parallel run needed
Two production incidents that taught us things
Incident one was self-inflicted. We'd migrated the inbound-call → GHL contact creation workflow to n8n with what we thought was identical logic. Three days into production-only running, we noticed a small but real drop in matter creation rate. The root cause: the old Zapier setup had a 30-second debounce on duplicate calls (same number within 30 seconds = treat as one). Our n8n version didn't. So when callers redialed within seconds, we created duplicate contacts and split matters. We hadn't documented the debounce because it was a Zapier-specific feature we'd tweaked once 14 months ago and forgotten about. Lesson: when migrating, audit not just the workflows you wrote but the platform behaviors you implicitly depend on.
Incident two was a Clio rate-limit issue. n8n is faster than Zapier on the happy path because it's not waiting in a SaaS queue. But that meant our spike-traffic days hit Clio's API rate limits we'd never hit before. Matters started failing to create in real time. We added exponential backoff with jitter on Clio writes and a fallback queue for matters that couldn't be created within the rate-limit window — they get created within 15 minutes when capacity returns. Total matters lost: zero since the fix. Total matters created with a 5-15 minute delay: a few per spike day, which is acceptable.
What I'd skip if I started today
Most of the medium- and low-stakes workflows. In retrospect, half of them existed because building them in Zapier was cheap; if we were starting on n8n, we wouldn't write them. 'Send me a Slack message when an opportunity stage changes' wasn't valuable enough to maintain across two systems. We deleted about 25 workflows during the migration just by asking 'do we actually need this?' on each one. That alone is worth doing periodically, regardless of which workflow tool you're on.





