Artur Lusmägi
Founder

n8n Support Options Compared: What Each Channel Actually Guarantees (2026)

August 13, 2026

n8n-supportn8n-slan8n-enterprisen8n-community-editionself-hosting

TL;DR: One line in n8n's own scope-of-support document decides most of this question: "Our support services do not include debugging custom code or third-party code or implementations." That exclusion holds on every plan, Enterprise included. So does the exclusion of community nodes, custom nodes, your infrastructure, and third-party services. Support covers the n8n product, not your automation. On top of that, n8n states plainly that Enterprise customers "do not receive service level agreements (SLAs) on severity levels as part of the standard support offering" and that severity levels "do not imply any guaranteed response or resolution times." A guaranteed response time exists only if you buy a separate support contract. Below is what each channel is actually obliged to do, and a script that scores how badly a failure would hurt you.

What does n8n support actually cover?

n8n supports the n8n product, used per its documentation, deployed on an official n8n Docker image. Everything else is out of scope on every tier: custom code, community and custom nodes, your infrastructure, third-party services, and staging or development environments. That set of exclusions covers most of what actually takes an automation down.

This is the part people skip. They compare tiers by reading the pricing page, see "Dedicated support with SLA" next to Enterprise, and assume the top tier means someone owns their broken workflow. It does not. The tiers change who may open a ticket and how quickly it gets looked at. They barely change what is in scope, and scope is what bites.

The matrix

Rows are support channels. Every cell traces to n8n's pricing page, its scope-of-support article, or its Cloud Enterprise terms.

ChannelCan you file a support ticket?Workflow debugging in scope?Guaranteed response timeSupport hours
Community forum (all users, incl. self-hosted Community Edition)No ticket. Forum thread only. n8n's support team monitors the forum.Community best-effort. No obligation.NoneNone stated
Self-hosted Community EditionNo. Forum only.NoNoneNone
Cloud Starter / ProOnly for billing, login or registration, an unavailable instance, or a reproducible bug on the latest stable version.No. n8n states it is "unable to provide in-depth debugging, troubleshooting, or deployment/runtime assistance for non-enterprise customers."None. All non-enterprise issues get "static priority" regardless of severity.Mon-Fri, 09:00-17:00
Business (self-hosted)n8n's pricing FAQ: "The Business Plan is a self-serve option and dedicated support is supported only in our Enterprise plan."NoNoneNot applicable
Enterprise (Cloud or self-hosted)Yes, incl. deployment errors and workflow execution errors, with a reproducible minimal example.Yes, for n8n's own execution errors. Still excludes custom code, community nodes, your infra, third-party services.No. "Enterprise customers do not receive service level agreements (SLAs) on severity levels as part of the standard support offering." Tickets get queue priority over non-enterprise.Mon-Fri, 09:00-17:00 (Europe/Berlin or America/New_York), excluding German public holidays
Enterprise plus a separate support contractYesSame scopeYes. "Guaranteed response times are available with a dedicated enterprise support contract." First response only, not resolution.Per contract
Third-party retainerYes, if the contract says soOnly if the contract says soOnly if the contract says soPer contract

Two columns do the work here. "Guaranteed response time" is empty for everything you can buy self-serve. "Workflow debugging in scope" is empty for everything below Enterprise.

Does the n8n community forum guarantee anything?

No. The forum carries no service level agreement, no response-time target, and no severity triage. n8n's support team does monitor forum questions and discussions, and n8n engineers participate, but nothing obliges anyone to answer your thread at all, let alone by a deadline.

It is also not the fallback channel. It is the primary channel for most paying customers: n8n states that "customers on our non-enterprise plans are expected to use the Forum to discuss suspected platform issues." Community Edition users have nothing else.

That is a reasonable deal for a free product, and the forum is genuinely good for the class of problem where somebody else has already hit the same wall. It is a bad deal for anything time-sensitive and specific to your instance, because the people best placed to answer that have no visibility into it.

What do Cloud Starter and Pro plans get beyond the forum?

An email address, for a short list of things. n8n will take a ticket from a Cloud plan customer when the request concerns a billing issue, a login or registration issue, an instance that is unavailable, or a reproducible bug on the latest stable version. Your workflow returning wrong data is on none of those lists.

The pricing page lists "Forum support" as the support feature for Starter and Pro. The scope-of-support article is blunter about the ceiling: n8n is "unable to provide in-depth debugging, troubleshooting, or deployment/runtime assistance for non-enterprise customers." And for prioritisation, non-enterprise tickets get "static priority": every issue is treated the same regardless of severity, so declaring your outage business-critical changes nothing.

Read those two together and Cloud's support value is narrow but real: if the platform itself is down or your instance will not boot, that is n8n's problem and they will work it. If your automation is broken and n8n is fine, you are on your own no matter which self-serve plan you are paying for.

What does the Enterprise SLA actually guarantee?

Less than the pricing page implies. The pricing page advertises "Dedicated support with SLA" for Enterprise. The scope-of-support article then states that "Enterprise customers do not receive service level agreements (SLAs) on severity levels as part of the standard support offering" and that "for guaranteed SLAs aligned to severity levels, a separate support contract must be in place."

What standard Enterprise support does guarantee is worth naming precisely, because it is not nothing:

  • Queue priority. "Enterprise customer tickets are prioritized over non-enterprise tickets." That is a relative promise, not a temporal one.

  • A real scope extension. Enterprise is the only tier where n8n will look at workflow execution errors, provided you supply actual behaviour, expected behaviour, steps to reproduce, what you tried, what changed since the last successful run, and an exported minimal example workflow.

  • Severity classification, which n8n explicitly says is for internal prioritisation and does "not imply any guaranteed response or resolution times."

Three more details change how you should plan. Target times refer to "the time it takes for n8n to provide a first response to your request, not the subsequent responses or issue resolution", so even a purchased SLA buys a reply, not a fix. Support runs Monday to Friday, 09:00 to 17:00, in Europe/Berlin or America/New_York, excluding German observed holidays. And uptime is a separate promise from support: the Cloud Enterprise terms commit to "commercially reasonable endeavours" toward 99.5% availability, excluding planned maintenance in a 10:00 to 17:00 German-time window.

Note what 99.5% permits. It is an availability target for n8n's platform, not a statement about your workflows, and it does not pay you back the executions you missed.

Which failures does nobody at n8n cover?

The common ones. Support scope excludes, on every tier: custom code, custom nodes including community nodes, your infrastructure, third-party services, and non-production environments. Deployment support additionally requires that n8n runs on an official n8n Docker image.

Walk through what actually breaks a production automation and check it against that list. A Code node throwing on an edge case is custom code. A community node breaking after an upgrade is a community node. A vendor rotating an API contract or rate-limiting you is a third-party service. Your Postgres filling its disk, your reverse proxy dropping websockets, your container being OOM-killed is your infrastructure. An OAuth token expiring silently is arguably yours too.

That is the whole failure surface for most teams, and all of it sits outside every n8n support tier. This is not a gotcha. It is the correct scope for a product vendor. It just means the tier you buy is the wrong lever to pull if what you want is "someone makes my automation work again."

What can a third-party retainer guarantee that n8n's tiers cannot?

Only what its contract says, which is exactly the point: it is the one option where scope and response time are written by you rather than published by a vendor. A retainer is worth buying when it covers the failure surface n8n excludes, and worthless when it is just a slower forum with an invoice attached.

If you are evaluating one, the contract needs to name four things explicitly:

  • Scope that includes your code and your vendors. Workflow logic, Code nodes, community nodes, credential rotation, and third-party API changes have to be in scope by name, since those are precisely the things the vendor excludes.

  • Infrastructure boundaries. Whether the host, database, and reverse proxy are covered, or stop at the n8n container. If nobody owns the VPS, nobody owns the outage.

  • A response window, and whether it extends beyond business hours. Ask for first response and what happens next. A first-response guarantee with no engagement commitment after it is theatre.

  • Who watches. Support that starts when you file a ticket only helps if you know something broke. Monitoring and alerting has to be in scope, or you are still the detection system.

When not to buy one: if you run a handful of Cloud workflows on official nodes with an error workflow wired up, a retainer is dead weight. Forum plus alerting genuinely covers you. The calculus changes when workflows are load-bearing for revenue, when they touch systems whose owners have moved on, or when self-hosting made your infrastructure your problem. That trade is the real content of the Cloud versus self-hosted decision, and it is worth deciding deliberately rather than discovering it after the fact.

How exposed is your instance right now?

Run the audit below before you shop for support. It scores your instance out of 100 across the five things that decide how much a failure costs you: active workflows with no error workflow assigned, credentials with a single owner, secrets pasted into HTTP Request nodes instead of credential objects, active workflows nobody has touched in months, and whether your encryption key is backed up.

The first four run against the n8n Public REST API v1. The fifth cannot: N8N_ENCRYPTION_KEY lives on the host, and if it was never set explicitly, n8n generated a random one into ~/.n8n/config at first boot. Lose that file and every stored credential is unrecoverable ciphertext, database backup or not. That check carries the heaviest penalty in the score for a reason.

You need an API key from the instance owner or an admin, because GET /credentials is owner and admin only. Create one under Settings, n8n API. A key with fewer permissions gets a 401 and the script exits rather than reporting a flattering score it could not actually verify.

export N8N_API_KEY='n8n_api_...'
node n8n-bus-factor-audit.mjs --url https://n8n.example.com --stale-days 90

Run it on the n8n host with the encryption key present to make the fifth check mean something, and pass --fail-under to turn it into a CI gate:

export N8N_ENCRYPTION_KEY='...'
node n8n-bus-factor-audit.mjs \
  --url https://n8n.example.com \
  --key-backup /secure/n8n-encryption-key.txt \
  --fail-under 80

Output looks like this:

n8n bus-factor audit  https://n8n.example.com
2 workflows (2 active), 2 credentials
------------------------------------------------------------------------
SCORE: 56/100
------------------------------------------------------------------------
Encryption key not provably backed up                1     -30
Active workflow with no error workflow               1     -3
HTTP Request node with a pasted secret               1     -8
Single-owner credential used by an active workflow   1     -2
Active workflow untouched in 90+ days                1     -1

ENCRYPTION KEY
  ! N8N_ENCRYPTION_KEY is not set in this process. If it is not set for the n8n
    process either, n8n generated a random key into ~/.n8n/config on first boot.

ACTIVE WORKFLOWS WITH NO ERROR WORKFLOW (they fail silently)
  - Stripe to Sheets  [w1]

SECRETS PASTED INTO HTTP REQUEST NODES (not in a credential object)
  - Stripe to Sheets > HTTP Request  [w1]
      parameters.headerParameters.parameters.Authorization: secret-bearing header/query parameter set to a literal value

The weights are a judgement call, not a measurement, and the script says so in a comment. Argue with them and edit them. What matters is that the same instance scores the same way next quarter, so you can tell whether you are getting safer or just busier.

The script

Save as n8n-bus-factor-audit.mjs. Node 18 or later, no dependencies.

#!/usr/bin/env node
/**
 * n8n bus-factor audit. Scores how badly a broken n8n instance would hurt you.
 * Node 18+, no dependencies. MIT licence. https://n8nlogic.com
 *
 *   export N8N_API_KEY='...'   # owner or admin key: GET /credentials is owner/admin-only
 *   node n8n-bus-factor-audit.mjs --url https://n8n.example.com
 *
 * Options: --stale-days <n> (default 90), --key-backup <path>, --fail-under <n>, --json
 */

import { readFileSync, statSync } from 'node:fs';

// --- args -------------------------------------------------------------------

const argv = process.argv.slice(2);
const arg = (name) => {
	const i = argv.indexOf(name);
	if (i === -1) return undefined;
	const value = argv[i + 1];
	if (value === undefined || value.startsWith('--')) {
		throw new Error(`Option ${name} requires a value.`);
	}
	return value;
};

const BASE_URL = (arg('--url') ?? '').replace(/\/+$/, '');
const STALE_DAYS = Number(arg('--stale-days') ?? 90);
const KEY_BACKUP = arg('--key-backup');
const FAIL_UNDER = arg('--fail-under') === undefined ? null : Number(arg('--fail-under'));
const JSON_OUT = argv.includes('--json');
const API_KEY = process.env.N8N_API_KEY;

if (!BASE_URL) throw new Error('Missing --url. Example: --url https://n8n.example.com');
if (!API_KEY) throw new Error('Missing N8N_API_KEY. Create one in n8n: Settings > n8n API.');
if (!Number.isFinite(STALE_DAYS) || STALE_DAYS <= 0) throw new Error('--stale-days must be a positive number.');

// --- API --------------------------------------------------------------------

async function apiGet(path, params = {}) {
	const url = new URL(`${BASE_URL}/api/v1${path}`);
	for (const [k, v] of Object.entries(params)) url.searchParams.set(k, String(v));

	const res = await fetch(url, {
		headers: { 'X-N8N-API-KEY': API_KEY, accept: 'application/json' },
	});

	if (!res.ok) {
		const body = await res.text();
		throw new Error(
			`GET ${url.pathname} failed: ${res.status} ${res.statusText}. ${body.slice(0, 300)}\n` +
				(res.status === 401 || res.status === 403
					? 'This endpoint needs an instance owner or admin API key. Do not downgrade the key and rerun: ' +
						'a partial audit is worse than none, because it will look clean.'
					: ''),
		);
	}
	return res.json();
}

async function apiGetAll(path, params = {}) {
	const items = [];
	let cursor;
	do {
		const page = await apiGet(path, cursor ? { ...params, cursor, limit: 250 } : { ...params, limit: 250 });
		if (!Array.isArray(page.data)) throw new Error(`Unexpected response shape from ${path}: no data array.`);
		items.push(...page.data);
		cursor = page.nextCursor ?? undefined;
	} while (cursor);
	return items;
}

// --- helpers ----------------------------------------------------------------

const daysSince = (iso) => (Date.now() - new Date(iso).getTime()) / 86_400_000;

// Header/query keys that carry a secret when they carry anything at all.
const SECRET_KEYS = /^(authorization|proxy-authorization|x-api-key|api-key|apikey|x-auth-token|private-token|token|access[_-]?token|secret|password)$/i;

// Values that are unmistakably a live credential rather than a placeholder.
const SECRET_VALUES = [
	/\bbearer\s+[A-Za-z0-9._~+/-]{12,}/i,
	/\bsk-[A-Za-z0-9_-]{16,}/,
	/\bxox[baprs]-[A-Za-z0-9-]{10,}/,
	/\bghp_[A-Za-z0-9]{20,}/,
	/\bgithub_pat_[A-Za-z0-9_]{20,}/,
	/\bAIza[A-Za-z0-9_-]{20,}/,
	/\bey[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/, // JWT
	/\bAKIA[0-9A-Z]{16}\b/,
	/\bglpat-[A-Za-z0-9_-]{16,}/,
];

// An n8n expression that pulls the value from somewhere safe is not a pasted secret.
const isSafeReference = (value) =>
	typeof value === 'string' && value.startsWith('=') && /\$(credentials|env|secrets|vars)\b/.test(value);

const looksLikeSecret = (value) =>
	typeof value === 'string' && value.length >= 12 && !isSafeReference(value) && SECRET_VALUES.some((re) => re.test(value));

/** Walk an HTTP Request node's parameters looking for a literal credential. */
function findInlineSecrets(node) {
	const hits = [];

	const visit = (value, trail) => {
		if (value === null || value === undefined) return;

		if (Array.isArray(value)) {
			// n8n stores headers/query as [{ name, value }, ...]
			for (const entry of value) {
				if (entry && typeof entry === 'object' && 'name' in entry && 'value' in entry) {
					const key = String(entry.name ?? '');
					const val = entry.value;
					if (SECRET_KEYS.test(key.trim()) && typeof val === 'string' && val.trim() !== '' && !isSafeReference(val)) {
						hits.push({ where: `${trail}.${key}`, reason: 'secret-bearing header/query parameter set to a literal value' });
						continue;
					}
					if (looksLikeSecret(val)) {
						hits.push({ where: `${trail}.${key}`, reason: 'value matches a known credential format' });
						continue;
					}
				}
				visit(entry, trail);
			}
			return;
		}

		if (typeof value === 'object') {
			for (const [k, v] of Object.entries(value)) visit(v, trail ? `${trail}.${k}` : k);
			return;
		}

		if (looksLikeSecret(value)) {
			hits.push({ where: trail, reason: 'value matches a known credential format' });
		}
	};

	visit(node.parameters ?? {}, 'parameters');
	return hits;
}

const HTTP_NODE_TYPES = new Set([
	'n8n-nodes-base.httpRequest',
	'n8n-nodes-base.httpRequestTool',
	'@n8n/n8n-nodes-langchain.toolHttpRequest',
]);

// --- checks -----------------------------------------------------------------

function checkEncryptionKey() {
	const envKey = process.env.N8N_ENCRYPTION_KEY;
	const result = { envKeySet: Boolean(envKey), backupPath: KEY_BACKUP ?? null, backupOk: false, notes: [] };

	if (!envKey) {
		result.notes.push(
			'N8N_ENCRYPTION_KEY is not set in this process. If it is not set for the n8n process either, n8n generated ' +
				'a random key into ~/.n8n/config on first boot. Lose that file and every stored credential is unrecoverable ' +
				'ciphertext, database backup or not.',
		);
	}

	if (!KEY_BACKUP) {
		result.notes.push('No --key-backup path given, so no backup could be verified.');
		return result;
	}

	const stat = statSync(KEY_BACKUP); // throws loudly if the "backup" is not there
	if (stat.size === 0) throw new Error(`Encryption key backup ${KEY_BACKUP} exists but is empty.`);

	const backed = readFileSync(KEY_BACKUP, 'utf8').trim();
	if (backed === '') throw new Error(`Encryption key backup ${KEY_BACKUP} contains only whitespace.`);

	if (envKey && backed !== envKey.trim()) {
		throw new Error(
			`Encryption key backup ${KEY_BACKUP} does not match N8N_ENCRYPTION_KEY. One of them is stale. ` +
				'Fix this before you need it.',
		);
	}

	result.backupOk = true;
	if (!envKey) {
		result.notes.push(
			`A backup file exists at ${KEY_BACKUP} but N8N_ENCRYPTION_KEY is not set here, so it could not be verified ` +
				'against the live key. Run this on the n8n host with the key in the environment.',
		);
	}
	return result;
}

async function audit() {
	const workflows = await apiGetAll('/workflows', { excludePinnedData: true });
	const credentials = await apiGetAll('/credentials');

	const live = workflows.filter((w) => !w.isArchived);
	const active = live.filter((w) => w.active);

	// 1. active workflows with no error workflow
	const noErrorWorkflow = active
		.filter((w) => !w.settings?.errorWorkflow)
		.map((w) => ({ id: w.id, name: w.name }));

	// credential id -> workflows using it, harvested from node payloads
	const credentialUsage = new Map();
	const inlineSecrets = [];

	for (const wf of live) {
		for (const node of wf.nodes ?? []) {
			for (const ref of Object.values(node.credentials ?? {})) {
				if (!ref?.id) continue;
				if (!credentialUsage.has(ref.id)) credentialUsage.set(ref.id, []);
				credentialUsage.get(ref.id).push({ workflowId: wf.id, workflowName: wf.name, active: wf.active });
			}

			if (!HTTP_NODE_TYPES.has(node.type)) continue;
			if (node.disabled) continue;

			const hits = findInlineSecrets(node);
			if (hits.length > 0) {
				inlineSecrets.push({
					workflowId: wf.id,
					workflowName: wf.name,
					node: node.name,
					usesCredentialObject: Object.keys(node.credentials ?? {}).length > 0,
					hits,
				});
			}
		}
	}

	// 2. credentials with a single owner
	const singleOwner = credentials
		.map((c) => {
			const shared = Array.isArray(c.shared) ? c.shared : [];
			const owners = shared.filter((s) => s.role === 'credential:owner');
			const usedBy = credentialUsage.get(c.id) ?? [];
			return {
				id: c.id,
				name: c.name,
				type: c.type,
				projects: shared.length,
				owner: owners[0]?.project?.name ?? null,
				usedByWorkflows: usedBy.length,
				usedByActiveWorkflows: usedBy.filter((u) => u.active).length,
			};
		})
		.filter((c) => c.projects <= 1);

	// 3. stale active workflows
	const stale = active
		.filter((w) => daysSince(w.updatedAt) > STALE_DAYS)
		.map((w) => ({ id: w.id, name: w.name, daysSinceUpdate: Math.floor(daysSince(w.updatedAt)) }))
		.sort((a, b) => b.daysSinceUpdate - a.daysSinceUpdate);

	// 4. encryption key
	const encryptionKey = checkEncryptionKey();

	// --- score ---------------------------------------------------------------
	// The weights below are a judgement call, not a measurement. Argue with them,
	// edit them, but write down why. What matters is that the same instance scores
	// the same way next quarter.
	const loadBearing = singleOwner.filter((c) => c.usedByActiveWorkflows > 0);

	const penalties = [
		{
			label: 'Encryption key not provably backed up',
			count: encryptionKey.backupOk && encryptionKey.envKeySet ? 0 : 1,
			each: 30,
			cap: 30,
		},
		{ label: 'Active workflow with no error workflow', count: noErrorWorkflow.length, each: 3, cap: 25 },
		{ label: 'HTTP Request node with a pasted secret', count: inlineSecrets.length, each: 8, cap: 20 },
		{ label: 'Single-owner credential used by an active workflow', count: loadBearing.length, each: 2, cap: 15 },
		{ label: `Active workflow untouched in ${STALE_DAYS}+ days`, count: stale.length, each: 1, cap: 10 },
	].map((p) => ({ ...p, deducted: Math.min(p.count * p.each, p.cap) }));

	const score = Math.max(0, 100 - penalties.reduce((sum, p) => sum + p.deducted, 0));

	return {
		instance: BASE_URL,
		generatedAt: new Date().toISOString(),
		score,
		totals: {
			workflows: live.length,
			activeWorkflows: active.length,
			credentials: credentials.length,
		},
		penalties,
		findings: {
			noErrorWorkflow,
			inlineSecrets,
			singleOwnerCredentials: singleOwner,
			loadBearingSingleOwnerCredentials: loadBearing,
			staleActiveWorkflows: stale,
			encryptionKey,
		},
	};
}

// --- report -----------------------------------------------------------------

function report(r) {
	const line = (s = '') => process.stdout.write(`${s}\n`);
	const pad = (s, n) => String(s).padEnd(n);

	line();
	line(`n8n bus-factor audit  ${r.instance}`);
	line(`${r.totals.workflows} workflows (${r.totals.activeWorkflows} active), ${r.totals.credentials} credentials`);
	line('-'.repeat(72));
	line(`SCORE: ${r.score}/100`);
	line('-'.repeat(72));

	for (const p of r.penalties) {
		line(`${pad(p.label, 52)} ${pad(p.count, 5)} -${p.deducted}`);
	}
	line();

	if (!r.findings.encryptionKey.backupOk || !r.findings.encryptionKey.envKeySet) {
		line('ENCRYPTION KEY');
		for (const note of r.findings.encryptionKey.notes) line(`  ! ${note}`);
		line();
	}

	if (r.findings.noErrorWorkflow.length) {
		line('ACTIVE WORKFLOWS WITH NO ERROR WORKFLOW (they fail silently)');
		for (const w of r.findings.noErrorWorkflow) line(`  - ${w.name}  [${w.id}]`);
		line();
	}

	if (r.findings.inlineSecrets.length) {
		line('SECRETS PASTED INTO HTTP REQUEST NODES (not in a credential object)');
		for (const s of r.findings.inlineSecrets) {
			line(`  - ${s.workflowName} > ${s.node}  [${s.workflowId}]`);
			for (const h of s.hits) line(`      ${h.where}: ${h.reason}`);
		}
		line();
	}

	if (r.findings.loadBearingSingleOwnerCredentials.length) {
		line('SINGLE-OWNER CREDENTIALS BEHIND ACTIVE WORKFLOWS');
		for (const c of r.findings.loadBearingSingleOwnerCredentials) {
			line(`  - ${c.name} (${c.type})  owner: ${c.owner ?? 'unknown'}  active workflows: ${c.usedByActiveWorkflows}`);
		}
		line();
	}

	if (r.findings.staleActiveWorkflows.length) {
		line(`ACTIVE BUT UNTOUCHED FOR ${STALE_DAYS}+ DAYS`);
		for (const w of r.findings.staleActiveWorkflows) line(`  - ${pad(w.name, 44)} ${w.daysSinceUpdate}d`);
		line();
	}
}

// --- run --------------------------------------------------------------------

const result = await audit();

if (JSON_OUT) {
	process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
} else {
	report(result);
}

if (FAIL_UNDER !== null && result.score < FAIL_UNDER) {
	process.stderr.write(`Score ${result.score} is below --fail-under ${FAIL_UNDER}.\n`);
	process.exit(1);
}

Fix in this order, because the penalties are ranked by how unrecoverable the failure is. An unbacked-up encryption key is the only item on the list that can destroy data you cannot rebuild. Pasted secrets are the only item that turns a workflow export into a credential leak. The rest is recoverable with time and swearing.

FAQ

Does the n8n Community Edition come with any support?

No. Community Edition users have the community forum and nothing else, with no service level agreement and no ticket channel. n8n's scope-of-support article puts non-enterprise plans in the same position: they are "expected to use the Forum to discuss suspected platform issues."

Does the n8n Enterprise plan include a guaranteed response time?

Not by default. n8n states that Enterprise customers "do not receive service level agreements (SLAs) on severity levels as part of the standard support offering," and that guaranteed response times require a separate dedicated enterprise support contract. Standard Enterprise support gives queue priority over non-enterprise tickets, not a clock.

Will n8n support debug my workflow?

Only on Enterprise, only for n8n's own workflow execution errors, and only if you supply a reproducible minimal example workflow along with expected behaviour, actual behaviour, and what changed. Errors caused by custom code, community nodes, your infrastructure, or third-party services are out of scope on every plan.

What are n8n's support hours?

Monday to Friday, 09:00 to 17:00, in Europe/Berlin for European customers and America/New_York for American customers, excluding German observed holidays. There is no published out-of-hours channel at any self-serve tier. Target response times also refer to the first response, not to resolution.

Is n8n Cloud's 99.5% uptime an SLA?

It is an availability commitment in the Cloud Enterprise terms, made under "commercially reasonable endeavours" and excluding planned maintenance during a 10:00 to 17:00 German-time window. It is a promise about n8n's platform, not about your workflows, and it is separate from anything support-related.

Do I need paid support if I self-host?

Not automatically, but understand what you have taken on. Self-hosting moves the entire infrastructure failure class, which no n8n tier covers anyway, onto you. If your score above is high and your workflows are not load-bearing, the forum is fine. If it is low, fix the score before you buy anything.

Where this leaves you

Buy the tier for the features, not for the safety net. Enterprise unlocks governance and gets your ticket looked at sooner, and if you genuinely need a guaranteed response time, the separate support contract is the only product on this page that sells one. But no n8n plan covers the failure surface that actually breaks automations, so the decision that matters is who owns your workflows, your integrations, and your host when they break.

If that person does not currently exist, an n8n specialist on retainer is the honest answer, and the audit score is a reasonable brief to hand them. We do this for teams whose n8n has quietly become load-bearing: tell us what you are running and we will tell you what is exposed before it costs you something.


n8n Support Options Compared: What Each Channel Actually Guarantees (2026) | n8nlogic