Auditing Low Code Workflows for SOC 2 and ISO 27001
TL;DR — Low-code workflows can pass SOC 2 Type II and ISO 27001 audits, but only with the same evidence discipline you apply to pro-code systems. Map controls, automate evidence collection, version workflows in git, and document the data flow. The audit isn’t where the work happens. The work happens before.
Compliance auditors are not impressed by “but it’s just a low-code workflow.” If the workflow touches in-scope data — customer PII, financial records, identity material — it’s in scope for the same controls everything else is. The shape of evidence is the same. The collection mechanism is what differs.
This is the last post in the September series on low-code in the enterprise. I’ve covered the pro-code engineer’s view, self-hosting, API exposure, webhook reliability, connectors, identity federation, and the decision matrix. This post is the compliance close-out. It’s the post I get asked to write most often by senior engineers who’ve just been told their citizen-dev program is in scope for the next audit cycle.
I’ll cover SOC 2 and ISO 27001 specifically because those are the two I’ve been through with low-code in scope. The principles transfer to PCI DSS, HIPAA, and the regional equivalents with minor adjustment.
The auditor’s actual questions
Strip away the formality and an auditor reviewing low-code workflows asks five things.
- Who can change the workflow, and how do you know?
- What does the workflow do with sensitive data?
- How would you know if the workflow malfunctioned, and what would you do?
- How do you remove access when someone leaves?
- Can you reconstruct what the workflow was doing on any given date in the past year?
Everything else is variation on those five. Build evidence for those, and the audit is mostly paperwork. Don’t, and you’ll be doing forensic archaeology under deadline pressure.
Mapping to SOC 2 Trust Service Criteria
SOC 2 organises its requirements around five Trust Service Criteria — Security, Availability, Processing Integrity, Confidentiality, Privacy. For each, here’s the low-code-specific control I’d ship.
Security (CC6)
CC6.1 — Logical access. Citizen developers authenticate to n8n and Make via SSO. Access is provisioned via group membership in the IdP. Local accounts are disabled. Evidence — IdP group membership exports, screenshots of disabled local-auth settings.
This is the payoff of the identity federation post. If you have that in place, this control is almost free.
CC6.6 — Logical access removal. Offboarding triggers IdP account disable, which propagates to platforms in under fifteen minutes. Evidence — your HRIS-to-IdP integration runbook plus a quarterly access review report.
CC6.7 — Restricted transmission. All workflow traffic to internal APIs goes through the citizen gateway (Kong 3.8 in my preferred stack), with TLS, scoped tokens, rate limits. Evidence — Kong route configurations exported, gateway access logs sampled.
CC6.8 — Malicious software protection. This sounds odd for low-code but it covers the question of “could a citizen dev exfiltrate data via a malicious node.” The answer is — connector library is allow-listed, arbitrary external HTTP from citizen workflows is blocked at the egress layer. Evidence — egress firewall config, the list of allowed external destinations.
Availability (A1)
A1.2 — Environmental protections / capacity / monitoring. Self-hosted n8n is deployed in queue mode with HA Postgres and Redis. Monitoring covers queue depth, worker health, execution error rate. Evidence — your runbook for the platform plus screenshots of the dashboards.
A1.3 — Recovery. Backups of n8n’s Postgres are nightly, retained 30 days, with at least one successful restore drill per quarter. Evidence — backup configuration, the restore-drill record.
Processing Integrity (PI1)
This is the criterion most directly affected by the at-least-once delivery model. The control language is “processing is complete, valid, accurate, timely, and authorised.”
PI1.1 — Complete and accurate processing. Critical workflows have idempotency keys, retry logic, and dead-letter handling. The webhook reliability post walked the patterns. Evidence — sample workflows showing the idempotency setup, dead-letter table contents (or attestation that the table is empty).
PI1.4 — Output is complete and accurate. Reconciliation between source and destination for any data-movement workflow. If an n8n workflow pulls 10,000 rows from Salesforce and writes 10,000 rows to BigQuery, you have a row-count check that runs daily and alerts on drift. Evidence — the reconciliation report and alert configuration.
Confidentiality (C1)
C1.1 — Identification and protection of confidential information. Confidential data flowing through low-code is documented in a data-flow inventory. PII fields are masked in execution logs. Evidence — the data flow inventory, sample log entries showing masking.
n8n 1.58 supports execution data redaction via the N8N_EXECUTIONS_DATA_HARDDELETE_BUFFER and explicit log scrubbing in nodes. Use them.
Privacy
If you’re claiming the privacy criterion, you’re committing to data-subject rights, retention limits, and explicit notice. That’s a bigger lift and probably means a Data Protection Officer involvement. Most teams I work with do not include privacy in SOC 2 — they handle privacy via a separate GDPR/CCPA program.
ISO 27001 mapping
ISO 27001 organises differently — controls are in Annex A, grouped by domain. The mapping for low-code is essentially the same content, different labels.
| ISO 27001 Annex A | What it looks like for low-code |
|---|---|
| A.5.15 Access control | SSO via IdP, group-based authorisation |
| A.5.17 Authentication information | MFA enforced at IdP, no shared passwords |
| A.5.18 Access rights | Quarterly access reviews, owner-stamped workflows |
| A.5.19 Information security in supplier relationships | DPAs with n8n cloud, Make, Auth0; review annually |
| A.8.1 User endpoint devices | Out of scope for the platform itself; covered by your endpoint policy |
| A.8.3 Information access restriction | Citizen gateway with scoped tokens |
| A.8.15 Logging | Gateway logs, n8n execution logs, IdP logs all shipped to SIEM |
| A.8.16 Monitoring activities | Alerts on error rate, unusual access, failed auth |
| A.8.25 Secure development life cycle | Version control of workflows (where supported), peer review for high-risk |
The ISO equivalent of the “Processing Integrity” criterion is split across A.8.25 (development) and A.8.32 (change management). Workflow changes have a documented review process for in-scope workflows. The platform team owns the cadence.
Evidence collection, automated
The big lift in any audit is evidence. Doing it manually under deadline is brutal. Automate everything you can.
Here’s a small Go 1.23 service that pulls evidence from the various sources daily and lands it in an S3 bucket the auditor can read.
package evidence
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
type EvidenceCollector struct {
s3 *s3.Client
bucket string
n8nAPI N8nClient
kongAPI KongClient
idpAPI IdPClient
}
type DailySnapshot struct {
CollectedAt time.Time `json:"collected_at"`
WorkflowCount int `json:"workflow_count"`
Workflows []WorkflowSummary `json:"workflows"`
GatewayTokens []TokenSummary `json:"gateway_tokens"`
IdPGroupCounts map[string]int `json:"idp_group_counts"`
ExecutionStats ExecutionStatsByDay `json:"execution_stats"`
}
func (c *EvidenceCollector) RunDaily(ctx context.Context) error {
snap := DailySnapshot{CollectedAt: time.Now().UTC()}
wfs, err := c.n8nAPI.ListWorkflows(ctx)
if err != nil {
return fmt.Errorf("list workflows: %w", err)
}
snap.WorkflowCount = len(wfs)
for _, wf := range wfs {
snap.Workflows = append(snap.Workflows, WorkflowSummary{
ID: wf.ID,
Name: wf.Name,
OwnerTag: wf.Tags["owner"],
Active: wf.Active,
UpdatedAt: wf.UpdatedAt,
NodeCount: len(wf.Nodes),
})
}
tokens, err := c.kongAPI.ListConsumers(ctx, "citizen")
if err != nil {
return fmt.Errorf("kong consumers: %w", err)
}
for _, t := range tokens {
snap.GatewayTokens = append(snap.GatewayTokens, TokenSummary{
Consumer: t.Username,
Scopes: t.ACLs,
LastUsed: t.LastUsed,
})
}
groups, err := c.idpAPI.GroupCounts(ctx)
if err != nil {
return fmt.Errorf("idp groups: %w", err)
}
snap.IdPGroupCounts = groups
snap.ExecutionStats, err = c.n8nAPI.StatsForDay(ctx, time.Now().AddDate(0, 0, -1))
if err != nil {
return fmt.Errorf("stats: %w", err)
}
body, _ := json.MarshalIndent(snap, "", " ")
key := fmt.Sprintf("evidence/%s/snapshot.json", time.Now().UTC().Format("2006/01/02"))
_, err = c.s3.PutObject(ctx, &s3.PutObjectInput{
Bucket: &c.bucket,
Key: &key,
Body: bytesReaderOf(body),
})
return err
}
The point is not the specific schema. It’s that every day, you snapshot enough state to answer the auditor’s reconstruction question. A year later, you can show what workflows existed, who owned them, how many nodes they had, when they last ran, and what tokens they used.
For ingestion to data warehouse for compliance reporting, Airbyte 1.0 (released August 2024) is a reasonable choice — it’s stable now and has connectors for most of the source systems you’d care about.
Versioning workflows
The single best thing you can do for the audit is have your workflows in git. n8n 1.58 supports git-backed environments in the paid plan, which exports workflows as JSON to a repo, with PR-based promotion between environments.
If you can’t run the paid plan, the next-best is a daily export job — call the n8n REST API, dump every workflow as JSON, commit to a repo. You lose the PR-review flow but keep the audit trail.
# Daily export, runs from your CI on a schedule
curl -sH "X-N8N-API-KEY: $N8N_KEY" "$N8N_HOST/api/v1/workflows" \
| jq -c '.data[]' \
| while read wf; do
id=$(echo "$wf" | jq -r '.id')
echo "$wf" | jq '.' > "workflows/$id.json"
done
git add workflows/
git commit -m "Daily snapshot $(date -u +%Y-%m-%d)" || true
git push origin main
Set the commit author to a service identity. The diff between yesterday and today is the change log. The repo is your evidence for control changes.
Make is more constrained — the API for exporting scenarios exists but is more limited. The pattern is the same, just less rich.
What auditors specifically ask for
In SOC 2 Type II audits I’ve been through where low-code was in scope, the auditor sample requests went roughly like this.
- “Show me the user list for n8n as of (date).” → IdP export filtered to the n8n group, with provisioning timestamps.
- “Show me access reviews for the past four quarters.” → Reports from your access-review tool, signed off by managers.
- “Walk me through this workflow.” → The auditor picks one. You explain the data flow, point at the data inventory, show the code or JSON in the repo.
- “Show me an incident in the workflow platform and the response.” → Your incident records, with timeline and resolution.
- “Show me the last restore test for the workflow database.” → The restore drill log entry.
- “How would I know if (specific bad thing) happened?” → The alert configuration.
None of those are exotic. They’re the same evidence patterns as for any other in-scope system. The mistake is assuming low-code is exempt because it’s “configuration not code.” The auditor will not buy that, correctly.
Common pitfalls
The repeat offenders.
- Treating low-code as out of scope by default. It’s only out of scope if it doesn’t touch in-scope data and you can prove that. Most citizen workflows touch SOMETHING that’s in scope.
- No data flow inventory. “What data flows through n8n?” should have a one-page answer. Most teams don’t have one until the auditor asks.
- Skipping access reviews on the platform. Every system in scope gets a quarterly access review. n8n and Make are no exception. Calendar it.
- No alerting on platform health. “Did the workflow fail?” should be auto-detected, not user-reported. Build the alerts before the auditor asks.
- Treating the audit as the work. The audit is the verification. The work is the year-round discipline. Companies that try to retrofit evidence in the two weeks before the audit fail. Build the controls in over months, not weeks.
- Forgetting third-party DPAs. If you use n8n cloud, Make, Auth0, or any other SaaS in scope, you need a Data Processing Agreement with the vendor. Review annually.
- Letting workflow ownership decay. A workflow without a documented owner is an audit finding. Tag every workflow with an owner email; review quarterly that the owner is still at the company and still owns it.
Wrapping up
Low-code workflows can absolutely pass SOC 2 Type II and ISO 27001. The controls are the same controls you already run for pro-code systems. The evidence collection is mostly an automation exercise — snapshot daily, version in git, log everything to SIEM. Done well, the audit takes the same effort as for any other component of your stack. Done badly, it’s a six-week scramble.
The wider point of this whole September series — low-code is real infrastructure. It deserves the same engineering discipline as anything else you run in production. The citizen developers do not need to know about queue mode, OAuth2 PKCE, HMAC signatures, or SOC 2 controls. The platform team does. That’s the deal.
That’s a wrap on this series. Thanks for reading along. October will move into different territory — back to backend system design, with some pieces on Go 1.23 in production and a few thoughts on event-driven architecture that’s been kicking around in my head. See you then.