KEEP LEARNING
Build the bigger picture.
The Workflow Engineer connects individual n8n concepts to testing, deployment and running a complete workflow.
Tips > Reliability & Performance
Some failures cannot be automatically retried or recovered.
A dead letter queue captures items a workflow cannot process automatically so they are never lost. Route each failed item to a Google Sheet, Postgres table, or dedicated queue along with its original payload, error details, and triage fields, then build a separate reprocessing workflow that reads pending rows and retries them. This gives your team a clear remediation path for every failure.
Some failures cannot be automatically retried or recovered. For these, route failed items to a dead letter queue (DLQ) -- a Google Sheet, database table, or dedicated queue where failed items wait for manual review and reprocessing. This prevents data loss and gives your team a clear remediation process.
Real-world example: A data migration workflow processes 10,000 records. 47 fail due to data quality issues (missing required fields, invalid formats). Rather than losing these records, route them to a DLQ sheet for the data team to fix and reprocess.
// Code node: "Prepare DLQ Entry"
// This runs on the failure branch after the "Split Successes/Failures" node
const failedItems = $input.all();
return failedItems.map(item => ({
json: {
// Identification
dlq_id: `DLQ-${Date.now()}-${Math.random().toString(36).substr(2, 6)}`,
created_at: new Date().toISOString(),
// Source information
workflow_name: $workflow.name,
execution_id: $execution.id,
source_node: 'Enrich Company Data',
// Original data (for reprocessing)
original_payload: JSON.stringify(item.json),
// Error details
error_message: item.json.error?.message || 'Unknown error',
error_code: item.json.error?.statusCode || null,
// Triage fields
status: 'pending', // pending | investigating | resolved | ignored
retryable: item.json.retryable || false,
assigned_to: null,
resolution_notes: null
}
}));Write to a Google Sheet (Dead Letter Queue):
Google Sheets node configuration:
Operation: Append
Sheet: "Dead Letter Queue"
Columns:
A: dlq_id
B: created_at
C: workflow_name
D: execution_id
E: source_node
F: original_payload
G: error_message
H: error_code
I: status
J: retryable
K: assigned_to
L: resolution_notesBuild a reprocessing workflow:
# Separate workflow: "DLQ Reprocessor"
# Triggered manually or on a schedule
[Manual Trigger or Schedule]
--> [Google Sheets: Read rows where status = 'pending' AND retryable = true]
--> [Code: Parse original_payload back to JSON]
--> [Original processing logic (copied or via Execute Workflow)]
--> [IF: Success?]
True: [Google Sheets: Update status to 'resolved']
False: [Google Sheets: Update status to 'investigating', increment retry_count]-- Postgres DLQ alternative (better for high volume)
CREATE TABLE dead_letter_queue (
id SERIAL PRIMARY KEY,
dlq_id TEXT UNIQUE NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
workflow_name TEXT NOT NULL,
execution_id TEXT,
source_node TEXT,
original_payload JSONB NOT NULL,
error_message TEXT,
error_code INTEGER,
status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'investigating', 'resolved', 'ignored')),
retryable BOOLEAN DEFAULT false,
retry_count INTEGER DEFAULT 0,
assigned_to TEXT,
resolved_at TIMESTAMPTZ,
resolution_notes TEXT
);
CREATE INDEX idx_dlq_status ON dead_letter_queue(status);
CREATE INDEX idx_dlq_created ON dead_letter_queue(created_at);No data is lost. Every failed item is accounted for and has a clear path to resolution, whether automatic retry or manual intervention.
Related: Use "Pin Data" to Freeze Node Output · Break Large Workflows into Sub-Workflows
KEEP LEARNING
The Workflow Engineer connects individual n8n concepts to testing, deployment and running a complete workflow.
APPLY IT TO YOUR SYSTEM
Bring the process, the tools involved and an example of where the current workflow gets stuck.