background-shape
Low Code in the Enterprise, A Pro Code Engineer's Honest View
September 2, 2024 · 8 min read · by Muhammad Amal programming

TL;DR — Low-code is not a threat to pro-code engineers, but pretending it doesn’t exist is. n8n 1.58 and Make in September 2024 are good enough to run real integrations. The job of a senior backend team is to set the guardrails, not to gatekeep.

I spent the first eight years of my career being smug about low-code. Drag-and-drop tools were what marketing ops used when they couldn’t get a Jira ticket through. The workflows were brittle. The audit trails were a joke. The auth model was “share a personal API token in a shared Notion page.” I had reasons.

Then around 2022 I watched a finance ops lead at a company I was consulting for build a Salesforce-to-NetSuite reconciliation flow in Make in two afternoons. It would have taken my team two sprints. It worked. It still works. I stopped being smug.

This post is the honest view I wish someone had given me earlier. It’s not a sales pitch for low-code. It’s a working model for how a senior backend org should think about citizen developers in 2024, when the tools have actually gotten good.

What low-code is actually good at in 2024

Low-code platforms in 2024 do three things genuinely well, and senior engineers should stop arguing the point.

Glueing SaaS together. When the business needs a flow between HubSpot, Slack, Google Sheets, and a webhook on your own service, the dev cost of writing that in Go or Node is mostly OAuth boilerplate and retry plumbing. n8n 1.58 and Make both have battle-tested OAuth flows for hundreds of SaaS apps. You don’t get to amortise that boilerplate across thirty integrations the way they do.

Visualising data flow for non-engineers. A Make scenario diagram is genuinely easier for a CFO to review than a main.go file. That matters for compliance, audits, and just plain trust. We pretend code is “self-documenting” and then ship 2000-line workflow services nobody reads.

Letting the business move at business speed. A field marketing lead does not want to file a backlog ticket to add a row to a Google Sheet when a Typeform fires. They want it done by Thursday. If you can’t ship that by Thursday, and they can ship it themselves by Tuesday, the build-vs-buy debate is over before it starts.

The pro-code engineer’s instinct is to argue that the resulting workflow is unmaintainable. Sometimes true. But the workflow that ships is worth more than the workflow that doesn’t. The trick is knowing which workflows belong in low-code and which don’t.

What low-code is genuinely bad at

I’ll be blunt. There are categories where citizen-developed workflows will hurt you, and your job as a senior engineer is to name them out loud.

Anything with a strict consistency requirement. Money movement, inventory deduction, identity provisioning. The retry semantics in most low-code tools are at-least-once with weak idempotency primitives. If your workflow charges a card, do not run it in Make.

Hot paths. A low-code platform sitting in front of a customer request is going to spike to 800ms p99 and fail occasionally with no useful trace. Citizen workflows belong behind a queue, never in the synchronous path of a user-facing call.

Anything that touches PII at scale without a DPIA. I’ve audited Make scenarios that piped full customer records through three SaaS vendors with no documented data-processor agreement. Not the tool’s fault. Process failure. And it’s a process failure the platform team owns, because nobody else in the company knows to ask.

Complex branching logic. Once a scenario has more than ten branches, it’s unreadable. At twenty, it’s a liability. I have a hard rule on teams I advise — when a Make scenario hits twenty modules or an n8n workflow hits twenty-five nodes, it gets a pro-code rewrite review.

A working split, by domain

Here’s the rubric I use when a business unit asks where to build something. It’s not exhaustive but it ends the argument fast.

Domain Low-code OK? Notes
Marketing automation Yes Owns its own data mostly
Sales ops (CRM glue) Yes Keep the citizen dev in the loop
Internal notifications Yes Slack/Teams/email
Finance reconciliation Conditional Read-only OK, writes need review
Identity provisioning No SCIM, audit, MFA, never citizen-owned
Payment flows No Period
Customer-facing webhooks No Pro-code with SLA
Data ingestion to warehouse Conditional Airbyte 1.0 if SaaS source, pro-code if custom

The “conditional” rows are where senior engineering should be paying attention. They’re where a citizen workflow can quietly grow into a production dependency without anyone noticing it crossed a line.

How a backend team should engage

The dismissive posture (I know, I held it for years) is to refuse to know anything about the low-code stack. That posture loses, because it cedes the platform decisions to whoever raises their hand first. By the time you hear about the workflow, it’s already loadbearing.

Engage like this instead.

Own the platform, not the workflows

Run n8n yourself. I’ll go deep on self-hosting n8n for engineering teams in the next post, but the short version is, when the platform sits on your infra, you control the egress, the secrets, the upgrade cadence, and the audit logs. You don’t have to own every workflow that runs on it. You own the runway.

Publish a connector library

The biggest win we’ve gotten on platform teams I’ve worked with is a curated set of internal-API connectors that citizen devs can drop into n8n or Make. These hide the auth, the retry, and the rate limiting behind a single node. The citizen dev gets “Send Invoice” instead of “construct OAuth header, sign, POST, parse 200, retry on 429.”

A minimal n8n custom node skeleton — this is the structure n8n 1.58 expects:

import { INodeType, INodeTypeDescription, IExecuteFunctions } from 'n8n-workflow';

export class AcmeInvoice implements INodeType {
  description: INodeTypeDescription = {
    displayName: 'Acme Invoice',
    name: 'acmeInvoice',
    group: ['transform'],
    version: 1,
    description: 'Create an invoice via the Acme internal API',
    defaults: { name: 'Acme Invoice' },
    inputs: ['main'],
    outputs: ['main'],
    credentials: [{ name: 'acmeApi', required: true }],
    properties: [
      { displayName: 'Customer ID', name: 'customerId', type: 'string', default: '' },
      { displayName: 'Amount (cents)', name: 'amount', type: 'number', default: 0 },
    ],
  };

  async execute(this: IExecuteFunctions) {
    const creds = await this.getCredentials('acmeApi');
    const customerId = this.getNodeParameter('customerId', 0) as string;
    const amount = this.getNodeParameter('amount', 0) as number;
    const res = await this.helpers.httpRequest({
      method: 'POST',
      url: `${creds.baseUrl}/v1/invoices`,
      headers: { Authorization: `Bearer ${creds.token}` },
      body: { customer_id: customerId, amount_cents: amount },
      json: true,
    });
    return [[{ json: res }]];
  }
}

That little package is worth a thousand “please don’t do that” Slack threads. The citizen dev gets the right behaviour because the alternative is harder than the right thing.

Give them a paved road, not a manual

Document three or four reference patterns. “How to listen to a webhook and write to BigQuery.” “How to consume a Kafka topic into Slack alerts.” “How to wrap a paginated SaaS API.” When the team asks how to build something, you point at the pattern. The point is not to constrain creativity. The point is that the seven thousandth Slack alerter on your platform should not look architecturally different from the first.

Be honest about who owns the incident

If a citizen-owned workflow goes down at 2am and pages the on-call SRE, somebody messed up the ownership matrix. Either the workflow needed to be pro-code with an SLA, or the page needs to route to the business unit that owns it. There is no third option that ends well.

Common pitfalls

A handful of things I see go wrong repeatedly on platform teams that have just opened up low-code.

  • Treating the platform as free. n8n’s self-hosted licence is free up to a point, but the database (Postgres), the workers, the cron, the secrets management, and the audit pipeline are not free. Budget like you would for any other internal platform. The n8n documentation on scaling covers what queue mode actually needs.
  • No environment separation. I’ve seen production scenarios in Make pointing at the production database, edited live, by the marketing intern. Build dev, staging, prod from day one.
  • Skipping the secrets review. Citizen devs will paste API keys in plain text into a “Set Variable” node if you let them. Use credentials objects, scoped tokens, and short rotations. If your platform doesn’t support credentials properly, that’s your blocker, not theirs.
  • No deprecation strategy for workflows. Workflows accumulate. By year two you’ll have hundreds and nobody knows which are live. Tag, owner-stamp, and prune quarterly.
  • Conflating “low-code” with “low quality.” A well-built Make scenario with proper error routes, idempotency keys, and a documented owner is better engineering than half the cron jobs in your codebase. Judge the artefact, not the tool.

Wrapping up

The framing I land on after several years of platform work is this. Low-code is a deployment target, not a development methodology. The interesting question is not “should we allow it” but “how do we run it like adults.” That means engineering ownership of the platform, a curated connector library, real audit, and an honest split of what does and doesn’t belong on it.

I’ll be writing the rest of this month on the practical pieces — self-hosting n8n, exposing APIs safely to citizen devs, webhook reliability patterns, identity federation, and an auditing playbook for SOC 2 and ISO 27001. If you’re a senior backend engineer who’s been told to “support the citizen developer initiative” and you’ve been quietly dreading it, I hope this series gives you a working model. The tools are good enough now. The remaining problem is mostly an organisational one, and that’s the one we’re paid to solve.