Core Workflow Patterns
Webhooks, schedules, conditional logic, loops, and error handling — the building blocks of every serious automation.
Completed Part 1 with a running n8n instance
~40 minutes
6 core patterns that power every n8n automation
Beyond the Basics
In Part 1, you deployed n8n on a RamNode VPS with automatic SSL and built a simple uptime monitor. That was a taste. Now we're going to learn the workflow patterns that make n8n genuinely powerful — the same patterns that replace hundreds of dollars worth of Zapier zaps and Make scenarios.
By the end of this guide, you'll understand the six core patterns that every n8n automation is built from. Master these, and you can automate almost anything.
Pattern 1: Webhooks — Let the World Talk to Your Workflows
Schedule triggers are great for polling, but webhooks let external services push data into your workflows in real time. This is how you connect n8n to GitHub, Stripe, Shopify, or any service that supports webhook notifications.
Building a Webhook Receiver
- Create a new workflow and add a Webhook node
- Set the HTTP method to POST
- Note the webhook URL — it will look like
https://n8n.yourdomain.com/webhook/abc123 - Set Authentication to
Header Authif you want to verify incoming requests
The moment you register this URL with an external service, every event that service sends will trigger your workflow instantly. No polling intervals, no delays, no wasted tasks.
Webhook Security
Never leave webhooks unprotected in production. Three approaches, from simplest to most robust:
Header Authentication — Require a secret token in the request headers:
Authentication: Header Auth
Header Name: X-Webhook-Secret
Header Value: your-secret-token-hereIP Allowlisting — Add an IF node after the webhook that checks {{ $request.headers['x-forwarded-for'] }} against a list of known IPs.
HMAC Validation — For services that sign payloads (like GitHub and Stripe):
const crypto = require('crypto');
const secret = 'your-webhook-secret';
const signature = $input.first().json.headers['x-hub-signature-256'];
const payload = JSON.stringify($input.first().json.body);
const expected = 'sha256=' + crypto.createHmac('sha256', secret)
.update(payload).digest('hex');
if (signature !== expected) {
throw new Error('Invalid webhook signature');
}
return $input.all();Responding to Webhooks
Some services expect a specific response from your webhook endpoint. Use the Respond to Webhook node at the end of your workflow to send back custom status codes and bodies. This is critical for services like Stripe that will retry if they don't get a 200 response.
Pattern 2: Advanced Scheduling
The Schedule Trigger is more flexible than a simple "every X minutes" timer.
Cron Expressions
For complex schedules, switch to Cron mode in the Schedule Trigger node:
| Schedule | Cron Expression |
|---|---|
| Every weekday at 9 AM | 0 9 * * 1-5 |
| First of every month at midnight | 0 0 1 * * |
| Every 15 min during business hours | */15 9-17 * * 1-5 |
| Every Sunday at 2 AM (maintenance) | 0 2 * * 0 |
Combining Multiple Triggers
A single workflow can have multiple triggers. Add both a Schedule Trigger and a Webhook trigger to the same workflow — the schedule handles routine checks while the webhook handles on-demand execution. This is something Zapier charges extra for (multi-step zaps with multiple triggers require higher-tier plans). In n8n, you just drag in another trigger node.
Pattern 3: Conditional Logic — IF, Switch, and Merge
The IF Node
The IF node evaluates a condition and routes data down one of two paths. Condition types you'll use most:
- String comparisons:
contains,starts with,ends with,regex match - Number comparisons:
greater than,less than,between - Boolean checks:
is true,is empty,exists
The Switch Node
When you need more than two paths, use the Switch node. Example — route support tickets by priority:
Value to check: {{ $json.priority }}
Rule 1: equals "critical" → Immediate PagerDuty alert
Rule 2: equals "high" → Slack notification to the team
Rule 3: equals "normal" → Add to ticket queue
Fallback: → Log and skipThe Merge Node
After conditional branches split your data, the Merge node brings paths back together. Three modes:
- Append: Combines all items from both inputs into one list
- Keep Key Matches: Only keeps items that exist in both inputs (inner join)
- Combine: Pairs items from input 1 with items from input 2
A common pattern is: split by IF → process each path differently → Merge back together → continue with unified data.
Pattern 4: Looping and Batch Processing
Implicit Looping
Most n8n nodes automatically process arrays. If an HTTP Request returns a list of 50 items, the next node receives all 50 and processes each one. You don't need an explicit loop for this.
The Loop Over Items Node
When you need explicit control — rate limiting API calls, processing batches, or running different logic per item:
- Add a Loop Over Items node
- Set Batch Size to control how many items process per iteration
- Connect the "loop" output back to the processing chain
- Connect the "done" output to the next step after all items are processed
HTTP Request (get 100 records)
→ Loop Over Items (batch size: 10)
→ HTTP Request (process each batch)
→ Wait (2 seconds — respect rate limits)
→ [loops back to Loop Over Items]
→ Done → Send Summary EmailThe Wait Node
The Wait node pauses execution for a specified duration. Essential for rate limiting, and also useful for delayed workflows — process an order → Wait 24 hours → Send a review request email. The Wait node saves the execution state and resumes later, so it doesn't hold system resources during the wait period.
Pattern 5: Data Transformation
Raw data from APIs and webhooks rarely arrives in the format you need. n8n provides several nodes for reshaping data.
The Set Node
Use the Set node to create clean output objects from messy inputs. Instead of passing through 50 fields from an API response, extract only the 5 you need using Manual Mapping mode with expressions like {{ $json.data.user.email }}.
The Code Node
When visual nodes aren't enough, the Code node runs JavaScript or Python directly:
// Transform an array of objects
const items = $input.all();
return items.map(item => ({
json: {
fullName: `${item.json.firstName} ${item.json.lastName}`,
email: item.json.email.toLowerCase(),
signupDate: new Date(item.json.created_at).toLocaleDateString(),
isActive: item.json.status === 'active'
}
}));Sometimes a 10-line script is clearer than a tangled node graph.
The Aggregate Node
When you need to collapse multiple items into a single summary — totals, counts, lists of values — the Aggregate node handles it. Useful for generating reports: process 100 records, then aggregate into a single summary item for the email node.
Pattern 6: Error Handling
This is where amateur automations fall apart and production automations shine. n8n gives you multiple layers of error handling.
Node-Level: Continue On Fail
On any node, go to Settings → Always Output Data and enable "Continue On Fail". Follow it with an IF node to detect errors:
{{ $json.error !== undefined }}Use this for nodes where failures are expected and recoverable — HTTP requests to flaky APIs, database queries that might return empty.
Workflow-Level: Error Trigger
Create a separate "Error Handler" workflow:
- Create a new workflow named
Global Error Handler - Add an Error Trigger node
- Add a Send Email or Slack node for notifications
- The Error Trigger provides: workflow name, node name, error message, execution URL, and timestamp
Set the Error Workflow in each workflow's settings to funnel every uncaught error into one alert pipeline.
Retry Logic
For transient failures, configure retries on individual nodes:
- Retry On Fail: Enable
- Max Tries:
3 - Wait Between Tries:
1000ms (increase for rate-limited APIs)
The Try/Catch Pattern
For critical workflow sections, build explicit error handling:
[Start]
→ HTTP Request (continue on fail)
→ IF (error detected?)
→ True: Log error → Notify → Stop
→ False: Continue processingPutting It All Together: A Real Workflow
Let's combine multiple patterns into a practical workflow — a form submission processor that receives data via webhook, validates it, saves it to a database, and sends notifications:
[Webhook — POST /form-submit]
→ [Code — Validate fields, sanitize input]
→ [IF — All required fields present?]
→ True:
→ [HTTP Request — Save to database API]
→ [IF — Save successful?]
→ True:
→ [Send Email — Confirmation to user]
→ [Slack — Notify team of new submission]
→ False:
→ [Error: Log and alert]
→ False:
→ [Respond to Webhook — 400 Bad Request with field errors]This workflow uses webhooks (Pattern 1), conditional logic (Pattern 3), data transformation (Pattern 5), and error handling (Pattern 6) — all running on your $5/month VPS with zero per-execution costs.
Debugging Workflows
- Execution Log — Every workflow execution is logged with full input/output data for each node. Go to Executions in the left sidebar to replay, inspect, and debug past runs.
- Manual Execution — Click "Test workflow" to run with test data. Use the Manual Trigger node during development, then swap it for your real trigger before activating.
- Pin Data — Right-click any node and select "Pin Data" to freeze its output. This lets you test downstream nodes without re-running the entire workflow.
What's Next?
In Part 3, we're connecting n8n to Ollama for local LLM processing — build AI-powered workflows that summarize documents, classify support tickets, generate content, and analyze data, all running on your VPS with zero API costs.
No OpenAI bills, no token metering, no data leaving your server.
