I was inside a client’s Zapier account doing what I can only describe as archaeological work, trying to understand why their monthly task count had jumped from twelve thousand to forty-seven thousand between October and November without anyone changing anything, when I found it. A Zap that was triggering on every new row in a Google Sheet, then using a Formatter step to split a comma-separated string into individual values, then looping through each value with a Looping by Zapier step. Each iteration counted as a task. The sheet had been getting a new row every few minutes from a form, each row had between eight and fifteen values in that field, and nobody had noticed because Zapier buries the task counter in the billing section rather than showing it on the Zap itself.
That client was on a plan that included ten thousand tasks a month. They had been paying overage charges for six weeks without realising it, because Zapier does not send an alert when you exceed your plan. It just charges you.
I rebuilt that entire workflow in n8n in about four hours. Self-hosted on their existing EC2 instance, Docker Compose, total cost of the migration in compute terms: negligible. The workflow has been running for eight months. They have paid nothing in task charges because there are no task charges, and the logic that Zapier was handling with three separate Zaps and a Looping step is now a single workflow with a Split In Batches node and an IF node that actually behaves correctly when the batch is empty, which the Zapier version did not.
I did not post about this on LinkedIn. The client did not post about it. It just happened, and then it was done, and both of us moved on.
This is why you are not reading about this migration publicly. It is not a story that anyone has a reason to tell out loud. The person who migrated does not want to admit they were on Zapier paying forty dollars per thousand tasks past their plan limit. The client does not know what tool is running their automations and does not need to. There is no launch post, no case study, no Twitter thread, because the whole point is that it works now and it did not before, and explaining that requires explaining what went wrong, and nobody likes doing that in public.
But the migrations are happening constantly. I know because I do some of them, and because the n8n Discord server has a channel that functions essentially as a Zapier debrief support group, people posting their old Zap structures and asking how to rebuild them, and the questions are not abstract, they are specific and they are detailed and they are from people who have clearly been running production workflows.
The thing Zapier does well is the first fifteen minutes. You connect two services, you map a field, it works. That experience is genuinely good and I will not pretend otherwise. The problem is that the first fifteen minutes is also approximately where Zapier’s ceiling starts to become visible. You need to iterate over a response array. You need conditional branching that goes more than two levels deep. You need to catch an error in one step and route it differently without the entire Zap failing. You need to parse a JSON response where the field you want is at response.data.items[0].attributes.value and the Formatter step is looking at you with the same blank expression it has for everything.

None of those things are impossible in Zapier. They are all just significantly more painful than they should be for a tool at that price point, and the price point is the part that eventually breaks people.
n8n has its own version of the first-fifteen-minutes problem, and I want to be honest about this because the documentation soft-pedals it. The self-hosted setup documentation will get you to a running instance, but it will not tell you that your WEBHOOK_URL environment variable needs to be set to your public domain before any trigger will work correctly, because by default it points to localhost and webhooks from external services will return successfully while delivering nothing. I spent an afternoon on this the first time. The docs described the variable, listed it in the example env file, and said nothing about the fact that getting it wrong produces no error, just silence. The workflow shows as active. The trigger fires in your test. Production does nothing. You find out because a client emails you.
The fix is one line in your docker-compose.yml. The documentation has since been updated to make this clearer, but at the time I was reading forum posts from 2021 to understand why a correctly configured webhook was not receiving anything.
What keeps me on n8n despite that, and despite the occasional 3am moment where a volume mount fails silently and I am reading Docker logs on my phone trying to understand why a workflow that was running fine yesterday is now returning 500s, is the Code node and what it represents. It means the tool has no ceiling. When the visual logic is not enough, I write ten lines of JavaScript and the problem is solved. When an API response is structured in a way no node was designed to handle, I handle it in code. That is not a workaround. That is the intended design. Zapier’s intended design is that you should not need to do that, and for simple automations that is a fine assumption, and for everything else it is the reason people leave.
Zapier is priced like enterprise software and built for the use case where nothing gets complicated. Most real automation gets complicated.

Olaitan Oladipo holds a BSc in Sociology from Olabisi Onabanjo University. He is a self-taught automation builder who has spent years inside n8n doing the work that most tutorials skip: debugging OAuth errors at 2am, migrating client automations from Make.com mid-project, fighting reverse proxy misconfigurations on AWS EC2, and figuring out through trial and error what actually holds up in production versus what only looks clean in a demo.
He is not a developer by training and not a SaaS founder. He is the person in the Discord server who actually answers the question instead of linking to the docs.
His writing on n8n Automation Tutorial covers self-hosting, AI agent workflows, tool comparisons, and the security vulnerabilities the automation industry would rather not discuss. He has built AI-assisted invoice approval flows using OpenAI function calling, connected Claude via HTTP Request nodes, and holds considered opinions about Zapier, Make.com, LangChain, and CrewAI that their marketing teams would not appreciate.
He writes for people who are technical enough to follow a tutorial but experienced enough to want the honest version.

