A 14-person freight forwarder I work with was paying $590 a month for a managed API gateway last year. Their total daily traffic: about 40 API calls. Peak days, maybe 60. The platform itself was fine, honestly. It was also enterprise-grade plumbing for a company whose entire integration surface amounted to “send orders to the ERP, send leads to the CRM.”
When they asked me to cut SaaS spend, the gateway was the second line on the spreadsheet. We replaced it with a self-hosted n8n instance on a Hetzner VPS that costs €4.50 a month (n8n’s sustainable-use license covers internal self-hosting for free, which is the entire reason this works). The n8n part of the migration took me about 20 minutes. First-timers should budget an hour and a coffee. Annual spend went from $7,080 to roughly €54, and nobody has complained once since.
If you’re currently choosing between an iPaaS and an API management tool, and you’re moving fewer than 50 calls a day, I’d gently suggest you’re choosing between two things you don’t need. We’ve done a detailed comparison of Zapier, Make, and n8n elsewhere, so this post stays narrow: the exact 4-step configuration we deploy for clients who refuse another monthly bill, and how to turn n8n into a genuinely boring little self-hosted API gateway.
Why your API gateway is probably overkill for under 50 daily calls
API management platforms sell a feature list built for a different life. OAuth token lifecycle, developer portals, per-consumer quotas, traffic analytics, spike protection, regional routing. All of it matters when dozens of external consumers are hammering your endpoints around the clock and you’re on the hook for SLAs.
Forty calls a day is one call every 36 minutes.
A typical SMB’s actual situation looks more like this: one website, a warehouse system, maybe a partner portal, talking to an ERP and a CRM. Known callers, predictable payloads, no developer onboarding. Paying Kong, Apigee, or MuleSoft prices for that is like commuting in a semi-truck because you might haul furniture someday.
And still, consultants keep prescribing exactly that. I’ve lost count of the discovery calls where a 20-person company tells me their previous agency put them on MuleSoft “for scalability.” Scalability toward what? They ship 30 orders a day.
One honest caveat before the steps, though. n8n is not an API management platform and I won’t pretend otherwise. What it can be is a self-hosted API gateway for low-volume, known-caller traffic, with auth, validation, rate limiting, routing, and monitoring baked in. That covers a surprising number of SMBs.
Step 1: Create a secured webhook endpoint in n8n with basic auth
Drop a Webhook node onto the canvas. Set the method (POST, almost always) and give the path an unguessable suffix, something like orders-7f3k9x instead of /orders. The path is obscurity rather than security, but it stops most drive-by scanning before it starts.
Then set Authentication to Basic Auth and create a credential with a username plus a long generated password. Every caller has to present those before the workflow executes anything, and n8n answers bad credentials with a 401 on its own. Header Auth works too if your callers prefer it; Basic is just the least configuration fuss.
Two settings matter more than people expect:
- Respond: switch it to “Using ‘Respond to Webhook’ Node.” Left on the default, n8n fires a 200 back before your ERP call has even run, which means you’re telling callers “success” while an order quietly fails.
- Production URL: test URLs die the moment you close the editor, so wire the production URL into your caller’s config and forget the other one exists.
Behind all of it, a reverse proxy with HTTPS. I use Caddy because the Let’s Encrypt setup is four lines, but Nginx is fine if you already run one. A gateway without TLS in 2025 is a non-starter for me; I’ll politely pass on the project.
Step 2: Add request validation and rate limiting without extra tools
Two jobs in this step: catch malformed payloads before they touch anything important, and stop a misbehaving caller from flooding you. n8n ships no dedicated nodes for either, which sounds like a problem until you realize an IF node and a Code node are kind of all you need.
Validation
An IF node right after the webhook, checking whatever your ERP will throw a fit about: order number exists, customer ID is numeric, line items aren’t empty. On the false branch, drop a Respond to Webhook node that returns a 400 with a JSON body naming the exact missing field. Specific errors mean callers fix their own bugs faster, and your ERP never sees garbage.
Rate limiting
This is the one part where n8n makes you do actual work. My approach is a Code node using workflow static data to keep a per-caller counter inside a time window. Under 100 requests an hour, pass. Over it, return a 429. Fifteen lines of JavaScript, roughly.
I’ll be straight with you: it’s the flimsiest piece of the whole setup. Static data resets when the workflow restarts, the counter lives per workflow, and a genuinely motivated attacker blows right past it. For an internal integration with one or two known callers, it’s honestly fine. For endpoints exposed to strangers, put Caddy’s rate limit module in front instead and treat my workaround as a seatbelt, not a wall.
And I do it at all because of a scar. Two years ago I shipped a client webhook with no rate limiting and a path that was, um, guessable. Turns out their POS vendor had pushed a buggy update that retried failed calls every 30 seconds, all night. 2,300 executions by morning. The Postgres database behind n8n grew about 4 GB, the instance got sluggish, and the client’s ops guy noticed before I did. I still feel stupid about that one. There was no elegant lesson at the time; I simply hadn’t thought about retries at all.
Step 3: Route to internal ERP and CRM with error branching
The Switch node does the heavy lifting here. Branch on payload type: “order” goes down the ERP path, “lead” goes to the CRM. For the freight forwarder, the ERP is a self-hosted Odoo and the CRM is Pipedrive, so the two branches are an HTTP Request node and a Pipedrive node. Your stack will look different. The pattern won’t.
On each branch, open the node settings and set On Error to “Continue (using error output).” That gives the node a second output, and you wire it into a failure branch: log the payload and the error to a Google Sheet (or Postgres, or wherever your team actually looks), fire a Slack message to whoever’s on call, and return a 502 to the caller. The caller knows it failed. You know it failed. The ERP didn’t receive a half-written order.
Flip on Retry On Fail while you’re in there, two or three attempts with a few seconds between them. Most ERP hiccups are transient and retries quietly absorb them. One warning from experience: your retries plus the caller’s retries is exactly how duplicate orders happen, so make the writes idempotent. If that word means nothing to you, we wrote a full walkthrough on building fail-safe API pipelines with idempotency.
Success path, failure path, retries in between. That skeleton is the same one we apply to every client build, and it’s really just workflow reliability engineering wearing an API costume.
Step 4: Monitor failures with n8n’s native execution logs
Nobody wants to babysit dashboards at this scale, and you don’t have to. The Executions tab is your monitoring: every run shows up with status, duration, and the full payload. A failed run can be opened, inspected down to the exact node that choked, fixed, and re-executed with the original data in about ten seconds. I’ve debugged production issues from my phone in a coffee line.
Three settings turn the logs from a liability into something usable:
- Execution data saving: save errors only, or keep success data for a few days. Otherwise the database grows forever and everything gets slow. Ask me how I know.
- Retention: 30 days for failed executions is plenty for a weekly skim.
- Error Trigger workflow: a separate workflow that fires on any failure in the project, wired to email or Slack. Logs tell you what happened; the error trigger tells you it happened. You need both halves, which is the short version of the monitoring philosophy behind our reliability engineering approach.
Then build a habit instead of a monitoring stack: every Monday, filter executions to errors and skim. The freight forwarder’s gateway has now run for 14 months. Last month it logged three failures, all on the Pipedrive side during an API wobble, all recovered by the retry. Total admin time runs about five minutes a week.
Where this stack stops making sense
Fair warning, because I’d rather you hear it from me than from an outage. No OAuth token management, no developer portal, no per-consumer analytics, no spike protection beyond my static-data counter. I’ve never pushed a single n8n instance past about 20,000 executions a day, so I genuinely don’t know where it degrades, and I won’t pretend to. Somewhere between 50 calls a day and a few thousand, real infrastructure starts earning its keep and this stops being the right answer.
If you’re still weighing platforms rather than architectures, the broader Zapier vs. Make vs. n8n comparison covers trade-offs well beyond API routing.
So that’s the whole self-hosted API gateway: one VPS at €4.50 a month, about an hour of setup the very first time, and five minutes of log-skimming a week, against $7,080 a year. I know which side of that trade I’d take for a 14-person company. Your calculus might differ if you’ve got compliance audits or a dozen external partners, and that’s fine. The point isn’t that API management tools are bad; most small companies were just never their customer.
If you build this, or you hit a wall halfway through, tell me how it went. I’m curious where other people’s ceilings land.
Talk soon,
Damian
