After building 50+ automations, here's when I reach for each tool - and when I don't.
Every week someone asks me: "Should I use n8n, Make.com, or just write code for this?" The honest answer is that each one wins in specific situations, and choosing wrong costs you time, money, or both. I've made all three mistakes. This guide is what I wish I had before I started.
I'll walk through real scenarios, cost structures, and the exact mental framework I use to pick the right tool in under five minutes.
Quick Verdict
If you're in a hurry:
- Make.com - visual thinkers, marketing teams, 1-100 scenarios with moderate complexity, budget under $50/month
- n8n - technical founders, complex logic, data privacy concerns, high volume, long-term cost efficiency
- Custom code - unique logic that no platform supports, maximum performance requirements, or when the automation is core to your product
Now let's go deeper.
Feature Comparison
| Feature | n8n | Make.com | Custom Code |
|---|---|---|---|
| Visual builder | Yes | Yes (better) | No |
| Custom JS/Python | Full support | Limited | Native |
| Error handling | Advanced | Basic | Full control |
| Scheduling | Built-in | Built-in | Your infrastructure |
| AI/LLM nodes | Built-in | Via HTTP | You build it |
| Self-hosting | Yes (open source) | No | Yes |
| Debugging | Good | Excellent | Your tools |
| Version control | JSON export | JSON export | Git |
| Team collaboration | Paid plans | Paid plans | Git-native |
| Community integrations | 400+ nodes | 1,000+ apps | Any API |
Make.com has more pre-built app connectors. n8n has better code flexibility. Custom code has none of the limitations and all of the complexity.
Pricing Comparison
Pricing models across these three options are fundamentally different, which makes direct comparison tricky.
n8n Pricing
| Plan | Cost | Executions |
|---|---|---|
| Self-hosted | $5-10/mo (server only) | Unlimited |
| Cloud Starter | $0/mo | 5K executions |
| Cloud Pro | $20/mo | Unlimited |
| Cloud Enterprise | Custom | Custom |
Self-hosting n8n on a $5 DigitalOcean droplet gives you unlimited executions with full data control. That is the real value proposition.
Make.com Pricing
| Plan | Cost | Operations/month |
|---|---|---|
| Free | $0 | 1,000 |
| Core | $10.59/mo | 10,000 |
| Pro | $18.82/mo | 10,000 + more features |
| Teams | $34.12/mo | 10,000 (per seat) |
| Enterprise | Custom | Custom |
Make.com charges per operation, not per scenario run. A single scenario with 10 modules costs 10 operations every time it runs. This adds up fast at volume.
Custom Code Pricing
Custom code has no platform cost - but it has real costs:
- Development time (your time or a contractor)
- Hosting infrastructure ($5-50/month depending on load)
- Maintenance and updates (ongoing)
- Monitoring and alerting (tools like Sentry, Datadog)
For a simple automation that runs once a day, custom code might cost $0/month to run but 8 hours to build. For something complex that runs thousands of times per day, it might be the cheapest option per execution.
Cost at Scale
| Monthly Volume | n8n Self-Hosted | Make.com | Custom Code (hosting) |
|---|---|---|---|
| 1K runs | $5 | $10.59 | $5-15 |
| 10K runs | $5 | $18.82 | $5-15 |
| 100K runs | $10 | $55+ | $10-30 |
| 1M runs | $20 | $200+ | $20-80 |
Above 10K monthly runs, n8n self-hosted consistently wins on pure cost.
Cost at Scale
Monthly cost comparison at 100K automation runs
Unlimited executions on self-hosted
Cost scales with operation count
Cheapest per-run at high volume
When to Use n8n
n8n is my default choice for technical clients who need serious automation without the Zapier tax. Here is when it earns that position.
You Have Complex Logic
n8n's Code node gives you full JavaScript and Python inside your workflows. When a client needed to parse webhook payloads, run custom business logic, and make conditional API calls based on database lookups, all in one flow, n8n handled it cleanly. Make.com would have required workarounds or multiple disconnected scenarios.
You Care About Data Privacy
A healthcare client needed to automate appointment reminders without patient data leaving their infrastructure. Self-hosted n8n running inside their VPC solved it. There is no Make.com equivalent for that requirement.
Your Volume Is High
At 50,000+ automation runs per month, Make.com pricing gets painful fast. Self-hosted n8n at that volume costs the same as 1,000 runs: whatever your server costs.
You Want AI Deeply Integrated
n8n has native LLM nodes. You can build multi-step AI agents - call an LLM, evaluate the output with another node, branch based on the result, call a tool, and loop - without any HTTP gymnastics. This is increasingly where complex automations live.
Real n8n Examples from Client Work
Example 1: Lead scoring pipeline. A B2B SaaS company had 300+ inbound leads per week. Built an n8n workflow: webhook receives form submission, Code node runs enrichment logic against Clearbit API, OpenAI node scores the lead 0-100 based on ICP criteria, Switch node routes to Slack for hot leads and HubSpot for all leads. Cut manual qualification time from 4 hours/day to zero.
Example 2: E-commerce order sync. A Shopify store needed real-time syncing across three warehouses with custom priority logic. The business rules were too complex for Make.com's routing. n8n's Code nodes handled the inventory allocation algorithm and the whole thing ran on a $10 VPS.
Example 3: AI content repurposing. Blog post published to WordPress, n8n webhook fires, LangChain agent extracts key points, generates five Twitter posts and a LinkedIn version, queues to Buffer via API, and sends a Slack notification with preview. Took three hours to build and saves six hours per week.
When to Use Make.com
Make.com deserves more credit than it gets from developers. The visual scenario builder is genuinely excellent, and for non-technical teams, it's the right call more often than not.
Your Team Is Not Technical
Make.com's interface is the best in class for visual workflow building. You can hand it to a marketing manager, ops lead, or founder who knows nothing about code and they will figure it out. n8n is more opinionated and requires more patience.
You Need Quick Setup With Common Apps
Make.com has 1,000+ pre-built app connectors with polished UIs for authentication. Connecting HubSpot, Slack, Airtable, Gmail, and Typeform is genuinely click-and-done. n8n has OAuth support too, but Make.com's connectors tend to expose more of each app's API surface through the visual UI.
Your Complexity Is Moderate
Branching, filtering, aggregating, iterating - Make.com handles all of this well visually. The problems start when you need custom logic that doesn't map to a pre-built module. At that point you're writing HTTP requests anyway and n8n becomes the better choice.
Real Make.com Examples from Client Work
Example 1: Marketing reporting dashboard. A 10-person agency needed weekly reports pulling data from Google Ads, Facebook Ads, and HubSpot into a Google Sheet. A marketing coordinator built the entire Make.com scenario in a day using their pre-built connectors. No developer time needed.
Example 2: Client onboarding sequence. A consulting firm triggered a multi-step onboarding: new client signs in Docusign, Make.com starts a sequence - creates Notion workspace, sends welcome email, adds to HubSpot, creates Slack channel, schedules kickoff in Calendly. Non-technical ops person built and maintains it.
Example 3: Social media monitoring. Brand monitoring across Twitter, Reddit, and Google Alerts, filtering for specific keywords, deduplicating mentions, routing to Slack or Notion based on sentiment. The scenario is complex visually but uses only pre-built modules, Make.com's strength.
When to Go Custom
Custom code is often the wrong answer - but when it's right, it's clearly right.
Your Logic Is Proprietary
If the automation logic itself is part of your competitive advantage, a pricing algorithm, a matching engine, a fraud detection system, you should not build it inside a third-party platform you do not control. Write the code. Own it.
You Need Peak Performance
Automation platforms add latency. A webhook hitting n8n might take 200-500ms to execute. A custom Node.js function on your own infrastructure can respond in under 20ms. For real-time systems, customer-facing interactions, or anything time-sensitive, that gap matters.
The Automation Is Part of Your Product
If you are building a feature that automates something for your users - not just internal process automation - you almost certainly need custom code. Users should not be aware that a third-party tool is running their experience.
You Have Unusual Integration Needs
Sometimes the API you need to call does not have an n8n node or Make.com module. Sometimes it requires OAuth flows, streaming responses, binary file handling, or custom authentication schemes that platforms cannot cleanly support. Custom code removes those constraints entirely.
Real Custom Code Examples from Client Work
Example 1: Real estate matching engine. Built a Node.js service that runs every 15 minutes, pulls new property listings from multiple APIs, scores them against buyer preference profiles using a custom algorithm, and sends personalized alerts. The matching logic was too business-specific for a no-code platform, and the client wanted to own the IP.
Example 2: Payment dunning system. A SaaS company needed custom retry logic for failed payments: retry at 3 days, 7 days, 14 days with different email copy each time, pause retries if the customer contacts support, restart if they update payment info. The branching conditions around customer state were too complex to maintain visually. Custom Node.js worker with a Postgres state machine handled it cleanly.
Example 3: Real-time webhook processor. A fintech client received 50,000 bank webhooks per day, each requiring sub-100ms processing to update customer account balances. Automation platforms were not a consideration. A Fastify server with a Bull job queue handled it.
Code Side by Side: The Same Automation in Each Tool
To make this concrete, here is the same automation implemented three ways: receive a form submission, enrich with company data, score the lead, and save to a CRM.
n8n Workflow (JSON excerpt)
This is what an n8n workflow node looks like in the exported JSON format:
{
"nodes": [
{
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"parameters": {
"path": "lead-capture",
"responseMode": "lastNode"
},
"position": [240, 300]
},
{
"name": "Enrich Lead",
"type": "n8n-nodes-base.httpRequest",
"parameters": {
"method": "GET",
"url": "https://company.clearbit.com/v2/companies/find",
"queryParameters": {
"parameters": [
{ "name": "domain", "value": "={{ $json.email.split('@')[1] }}" }
]
},
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"position": [460, 300]
},
{
"name": "Score Lead",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "const lead = $input.first().json;\nconst company = $('Enrich Lead').first().json;\n\nlet score = 0;\nif (company.metrics?.employees > 50) score += 30;\nif (company.metrics?.estimatedAnnualRevenue > 1000000) score += 25;\nif (lead.timeline === 'immediate') score += 25;\nif (lead.budget > 5000) score += 20;\n\nreturn [{ json: { ...lead, company, score, tier: score > 70 ? 'hot' : score > 40 ? 'warm' : 'cold' } }];"
},
"position": [680, 300]
},
{
"name": "Save to HubSpot",
"type": "n8n-nodes-base.hubspot",
"parameters": {
"resource": "contact",
"operation": "upsert",
"email": "={{ $json.email }}",
"additionalFields": {
"leadScore": "={{ $json.score }}",
"lifecyclestage": "={{ $json.tier === 'hot' ? 'opportunity' : 'lead' }}"
}
},
"position": [900, 300]
}
]
}n8n gives you expression syntax (={{ }}), native HubSpot nodes, and a Code node where you write real JavaScript. The workflow is version-controlled as JSON.
Make.com Scenario (Module config)
Make.com does not export as readable JSON in the same way, but here is what the module configuration looks like conceptually:
{
"scenario": {
"name": "Lead Capture and Score",
"modules": [
{
"id": 1,
"type": "webhook",
"name": "Receive Form Submission",
"config": { "method": "POST" }
},
{
"id": 2,
"type": "http.makeRequest",
"name": "Clearbit Enrichment",
"config": {
"url": "https://company.clearbit.com/v2/companies/find",
"method": "GET",
"qs": [{ "key": "domain", "value": "{{split(1.email, '@')[1]}}" }],
"headers": [{ "key": "Authorization", "value": "Bearer {{connection.apiKey}}" }]
}
},
{
"id": 3,
"type": "builtin.basicRouter",
"name": "Route by Company Size",
"routes": [
{
"label": "Large Company",
"filter": { "condition": "{{2.metrics.employees}}", "operator": "greater", "value": "50" }
},
{
"label": "Small Company",
"filter": { "condition": "{{2.metrics.employees}}", "operator": "less", "value": "50" }
}
]
},
{
"id": 4,
"type": "hubspot.createUpdateContact",
"name": "Save to HubSpot",
"config": {
"email": "{{1.email}}",
"properties": [
{ "name": "lead_score", "value": "75" }
]
}
}
]
}
}Notice what is missing: the actual scoring logic. Make.com would require a separate formula field or a router with multiple branches to approximate what the n8n Code node does in ten lines. For simple scoring this works, but the logic becomes unwieldy as conditions grow.
Custom Node.js Implementation
import Fastify from "fastify";
import { clearbit } from "./lib/clearbit";
import { hubspot } from "./lib/hubspot";
import { slack } from "./lib/slack";
const app = Fastify();
interface LeadPayload {
email: string;
name: string;
company: string;
timeline: "immediate" | "quarter" | "year";
budget: number;
message: string;
}
function scoreLead(lead: LeadPayload, company: ClearbitCompany): number {
let score = 0;
// Company signals
if ((company.metrics?.employees ?? 0) > 50) score += 30;
if ((company.metrics?.estimatedAnnualRevenue ?? 0) > 1_000_000) score += 25;
if (company.category?.sector === "Technology") score += 10;
// Lead signals
if (lead.timeline === "immediate") score += 25;
if (lead.budget > 10_000) score += 20;
else if (lead.budget > 5_000) score += 10;
return Math.min(score, 100);
}
app.post<{ Body: LeadPayload }>("/webhooks/lead", async (request, reply) => {
const lead = request.body;
// Enrich with company data
const domain = lead.email.split("@")[1];
const company = await clearbit.company.find({ domain });
// Score the lead
const score = scoreLead(lead, company);
const tier = score >= 70 ? "hot" : score >= 40 ? "warm" : "cold";
// Save to CRM
await hubspot.contacts.upsert({
email: lead.email,
properties: {
firstname: lead.name.split(" ")[0],
lastname: lead.name.split(" ").slice(1).join(" "),
lead_score: score,
lead_tier: tier,
lifecyclestage: tier === "hot" ? "opportunity" : "lead",
},
});
// Alert for hot leads
if (tier === "hot") {
await slack.postMessage({
channel: "#hot-leads",
text: `Hot lead: ${lead.name} at ${lead.company} (score: ${score})`,
});
}
return reply.code(200).send({ received: true, score, tier });
});
app.listen({ port: 3000 });This is cleaner to read, easier to test, and trivially extensible. The trade-off is that you wrote it, you host it, and you maintain it. There is no drag-and-drop.
Real Project Examples
Project 1: Agency Client Reporting (Make.com)
Client: 15-person digital marketing agency Problem: Manually pulling weekly reports from 6 ad platforms into Google Sheets took 5 hours every Monday Tool chosen: Make.com Why: Marketing team owns the automation, not the developer. Pre-built connectors for Google Ads, Meta Ads, LinkedIn Ads, and Google Sheets. No code needed. Result: 5 hours saved weekly. Marketing manager built and maintains it independently. Cost: $18.82/month on Make.com Pro
Project 2: SaaS Lead Qualification (n8n)
Client: B2B SaaS startup, 300+ inbound leads/week Problem: Sales team spending 4 hours/day manually scoring leads, hot leads going cold Tool chosen: n8n self-hosted Why: Needed custom scoring algorithm, OpenAI integration for message analysis, complex routing logic. Developer on team to maintain it. Result: 0 manual qualification hours. Response time under 2 minutes. 3x increase in hot lead conversion. Cost: $12/month (server + OpenAI)
Project 3: Real-Time Inventory Sync (Custom Node.js)
Client: Multi-location retail brand Problem: Inventory levels across 12 locations and 3 warehouses out of sync. Overselling happening daily. Tool chosen: Custom Node.js service Why: Required sub-200ms response time on order placement, complex allocation logic based on shipping zones, direct integration with proprietary warehouse management system Result: Zero oversells since launch. Order allocation accuracy 99.8%. Cost: $25/month (dedicated VM)
Decision Framework
When I get a new automation request, I work through these questions in order:
Automation Tool Decision Flowchart
Work through each question in order
1. Is this automation core to your product or user experience?
2. Does it require sub-100ms response time or 1M+ monthly executions?
3. Does it involve proprietary logic or data that must stay on your infrastructure?
4. Will a non-developer need to build or maintain this?
5. Does it need custom code, AI agents, or complex conditional logic?
Volume tiebreaker
If cost is a concern and monthly executions exceed 10K, self-hosted n8n beats Make.com every time regardless of other factors.
The Short Version
- Non-technical person needs to own it: Make.com
- Complex logic, AI integration, high volume, or data privacy: n8n
- Core product feature, unique algorithm, or sub-100ms performance needed: Custom code
Common Mistakes I See
Mistake 1: Using Custom Code for Commodity Automations
A developer sees a simple webhook-to-CRM flow and immediately spins up a Node.js service. That service now needs hosting, monitoring, deployment pipelines, and maintenance. n8n would have handled it in 20 minutes. Save custom code for when it actually matters.
Mistake 2: Using Make.com for High-Volume Workflows
A startup picks Make.com because it looks friendly. Six months later they have 500K monthly operations and a $300/month bill for what would cost $20 on self-hosted n8n. The migration is painful because their scenarios are complex. Plan for volume early.
Mistake 3: Building Complex Logic in Make.com Routers
Make.com's router with 8 branches and 40 filter conditions is a maintenance nightmare. If you find yourself building deeply nested routing logic in Make.com, you have outgrown it. Move to n8n where Code nodes keep that logic readable.
Mistake 4: Treating n8n as a Drop-In Zapier Replacement
n8n requires more setup and thought than Zapier or Make.com. If you set it up and immediately try to use it like Zapier - expecting everything to just work with no configuration - you will be frustrated. Invest a few hours understanding nodes, expressions, and credentials. It pays off.
Mistake 5: Not Planning for Failures
All three tools can and do fail. Webhooks get missed. API rate limits get hit. Third-party services go down. Make.com has decent built-in error handling. n8n has retry logic and error workflows. Custom code has whatever you build. Whatever tool you choose, design for failure from day one.
My Honest Take After 50+ Projects
Make.com is often underestimated by developers. For a non-technical team that needs to own their automations, it is the right call - even if the per-operation pricing model stings at scale. I have handed Make.com scenarios to marketing managers and operations coordinators who maintained them independently for months without calling me.
n8n is my daily driver for client work. The combination of visual building, Code nodes, self-hosting, and native AI support covers 80% of what I need. The learning curve is real but manageable. The economics at scale are hard to argue with.
Custom code I reserve for situations where the other tools genuinely cannot deliver. This happens less than you might expect. When it does happen, it is usually a performance requirement, a proprietary algorithm, or a product-level feature - and in those cases, there is no debate.
The worst outcome is mismatching tool to problem. Complex logic in Make.com becomes unmaintainable. Commodity workflows in custom code become expensive to maintain. Non-technical ownership of n8n becomes a support burden.
Pick the tool that matches your team, your volume, and the nature of the logic. That is the whole framework.
Working on an automation and not sure which direction to go? I offer free 30-minute calls to walk through your specific use case and recommend the right approach. Get in touch and we will figure it out together.