Skip to content

n8n Workflow Automation Cheat Sheet

Overview

n8n is a powerful, open-source workflow automation platform that enables users to connect different systems, services, and APIs to create automated workflows with minimal coding. What sets n8n apart from other automation tools is its unique combination of flexibility, extensibility, and AI capabilities, making it suitable for both simple automations and complex enterprise workflows.

As a self-hostable solution, n8n gives users complete control over their data and workflows, addressing privacy and security concerns that come with cloud-only solutions. Its node-based visual interface allows for intuitive workflow creation while still providing the depth and customization options that technical users need. With support for JavaScript transformations, conditional logic, error handling, and a growing library of integrations, n8n has emerged as a favorite among developers and technical teams looking to automate processes without sacrificing control or capabilities.

In the AI era, n8n has positioned itself as a key tool for orchestrating AI workflows, with built-in nodes for popular AI services and the ability to create custom integrations with any API-accessible AI model or service. This makes it an essential tool for organizations looking to incorporate AI into their business processes while maintaining governance and control.

Installation and Setup

Self-Hosted Installation

bash
# Using npm
npm install n8n -g
n8n start

# Using Docker
docker run -it --rm \
  --name n8n \
  -p 5678:5678 \
  -v ~/.n8n:/home/node/.n8n \
  n8nio/n8n

# Using Docker Compose
# Create docker-compose.yml with:
# version: '3'
# services:
#   n8n:
#     image: n8nio/n8n
#     restart: always
#     ports:
#       - "5678:5678"
#     volumes:
#       - ~/.n8n:/home/node/.n8n
#     environment:
#       - N8N_ENCRYPTION_KEY=your-secret-key
#       - N8N_PROTOCOL=https
#       - N8N_HOST=n8n.example.com

docker-compose up -d

Cloud Installation

n8n offers a cloud version at n8n.cloud with various pricing tiers, from free to enterprise.

Environment Configuration

bash
# Basic configuration
export N8N_ENCRYPTION_KEY=your-secret-key
export N8N_PROTOCOL=https
export N8N_HOST=n8n.example.com
export N8N_PORT=5678

# Database configuration (PostgreSQL)
export DB_TYPE=postgresdb
export DB_POSTGRESDB_HOST=postgres
export DB_POSTGRESDB_PORT=5432
export DB_POSTGRESDB_DATABASE=n8n
export DB_POSTGRESDB_USER=n8n
export DB_POSTGRESDB_PASSWORD=password

# Queue configuration (Redis)
export QUEUE_BULL_REDIS_HOST=redis
export QUEUE_BULL_REDIS_PORT=6379

# Authentication
export N8N_BASIC_AUTH_ACTIVE=true
export N8N_BASIC_AUTH_USER=admin
export N8N_BASIC_AUTH_PASSWORD=password

Core Concepts

Workflows

Workflows are the main building blocks in n8n. They consist of nodes connected together to define a process flow.

Nodes

Nodes represent actions, triggers, or operations in a workflow. Each node has specific functionality, like sending an email, querying a database, or processing data.

Connections

Connections link nodes together, defining the flow of data from one node to another.

Triggers

Triggers are special nodes that start a workflow execution, such as webhooks, schedules, or events from external systems.

Executions

Executions are instances of a workflow being run, either manually or automatically triggered.

Basic Workflow Creation

Creating a New Workflow

  1. Navigate to the n8n interface (default: n8n.example.com)
  2. Click "Workflows" in the sidebar
  3. Click "Create new workflow"
  4. Enter a name for your workflow
  5. Click "Save"

Adding and Connecting Nodes

  1. Click the "+" button to add a node
  2. Search for the desired node type
  3. Configure the node's settings
  4. Connect nodes by dragging from the output dot of one node to the input dot of another
  5. Click "Execute workflow" to test

Basic Workflow Example

javascript
// HTTP Request Node Configuration
{
  "url": "https://api.example.com/data",
  "method": "GET",
  "authentication": "Basic Auth",
  "username": "user",
  "password": "pass"
}

// Function Node to Transform Data
function transform(items) {
  return items.map(item => {
    return {
      id: item.json.id,
      name: item.json.name.toUpperCase(),
      created: new Date(item.json.created_at).toISOString()
    };
  });
}

// Send Email Node Configuration
{
  "to": "recipient@example.com",
  "subject": "Data Report",
  "text": "=== Please find the data report attached ===",
  "attachments": "={{ $json.report }}"
}

Triggers and Scheduling

Webhook Trigger

javascript
// Webhook Node Configuration
{
  "path": "incoming-data",
  "responseMode": "onReceived",
  "responseData": "firstEntryJson"
}

// Access in browser or via curl
// https://n8n.example.com/webhook/incoming-data
// curl -X POST -H "Content-Type: application/json" -d '{"data":"test"}' https://n8n.example.com/webhook/incoming-data

Schedule Trigger

javascript
// Cron Node Configuration
{
  "triggerTimes": {
    "item": [
      {
        "mode": "everyWeek",
        "hour": 9,
        "minute": 0,
        "dayOfWeek": 1 // Monday
      }
    ]
  }
}

// Every 5 minutes
{
  "triggerTimes": {
    "item": [
      {
        "mode": "everyX",
        "unit": "minutes",
        "value": 5
      }
    ]
  }
}

Trigger on File Changes

javascript
// Watch Files Node Configuration
{
  "folder": "/data/incoming",
  "includeSubfolders": true,
  "fileExtensions": [
    "csv",
    "xlsx"
  ]
}

Data Manipulation

Function Node

javascript
// Basic transformation
function transform(items) {
  return items.map(item => {
    return {
      ...item.json,
      fullName: `${item.json.firstName} ${item.json.lastName}`,
      age: calculateAge(item.json.birthDate)
    };
  });
}

function calculateAge(birthDate) {
  const today = new Date();
  const birth = new Date(birthDate);
  let age = today.getFullYear() - birth.getFullYear();
  const monthDiff = today.getMonth() - birth.getMonth();
  
  if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
    age--;
  }
  
  return age;
}

// Filtering data
function filter(items) {
  return items.filter(item => {
    return item.json.status === 'active' && item.json.age > 18;
  });
}

// Aggregating data
function aggregate(items) {
  const result = {
    count: items.length,
    sum: 0,
    average: 0,
    min: Infinity,
    max: -Infinity
  };
  
  items.forEach(item => {
    const value = item.json.amount;
    result.sum += value;
    result.min = Math.min(result.min, value);
    result.max = Math.max(result.max, value);
  });
  
  result.average = result.sum / result.count;
  
  return [{ json: result }];
}

Split In Batches Node

javascript
// Split In Batches Node Configuration
{
  "batchSize": 10,
  "options": {
    "includeBatchIndex": true
  }
}

Merge Node

javascript
// Merge Node Configuration
{
  "mode": "merge",
  "mergeByFields": {
    "values": [
      {
        "field1": "id",
        "field2": "userId"
      }
    ]
  }
}

// Concatenate mode
{
  "mode": "concatenate"
}

// Multiplex mode (combine all items from all inputs)
{
  "mode": "multiplex"
}

Error Handling and Flow Control

Error Workflow

javascript
// Error Trigger Node
// This node triggers when another workflow fails

// Error Workflow Example
// 1. Error Trigger Node
// 2. Send Email Node with error details
{
  "to": "admin@example.com",
  "subject": "Workflow Error: {{ $workflow.name }}",
  "text": "Error in workflow: {{ $workflow.name }}\n\nError: {{ $json.error }}\n\nExecution ID: {{ $execution.id }}"
}

IF Node

javascript
// IF Node Configuration
{
  "conditions": {
    "string": [
      {
        "value1": "={{ $json.status }}",
        "operation": "equal",
        "value2": "success"
      }
    ]
  }
}

// Multiple conditions with AND/OR
{
  "conditions": {
    "string": [
      {
        "value1": "={{ $json.status }}",
        "operation": "equal",
        "value2": "pending"
      }
    ],
    "number": [
      {
        "value1": "={{ $json.amount }}",
        "operation": "larger",
        "value2": 1000
      }
    ],
    "boolean": [
      {
        "value1": "={{ $json.isVIP }}",
        "operation": "equal",
        "value2": true
      }
    ],
    "combinationMode": "any" // "all" for AND, "any" for OR
  }
}

Switch Node

javascript
// Switch Node Configuration
{
  "rules": {
    "values": [
      {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.status }}",
              "operation": "equal",
              "value2": "new"
            }
          ]
        },
        "outputIndex": 0
      },
      {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.status }}",
              "operation": "equal",
              "value2": "processing"
            }
          ]
        },
        "outputIndex": 1
      },
      {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.status }}",
              "operation": "equal",
              "value2": "completed"
            }
          ]
        },
        "outputIndex": 2
      }
    ]
  },
  "fallbackOutput": 3
}

Wait Node

javascript
// Wait Node Configuration
{
  "amount": 5,
  "unit": "minutes"
}

// Wait until specific date
{
  "dateTime": "={{ new Date($json.scheduledTime).toISOString() }}"
}

Working with APIs

HTTP Request Node

javascript
// Basic GET request
{
  "url": "https://api.example.com/users",
  "method": "GET",
  "authentication": "None",
  "options": {}
}

// POST request with JSON body
{
  "url": "https://api.example.com/users",
  "method": "POST",
  "authentication": "Bearer Token",
  "token": "{{ $node['Get Token'].json.access_token }}",
  "bodyContentType": "json",
  "body": {
    "name": "{{ $json.name }}",
    "email": "{{ $json.email }}",
    "role": "user"
  },
  "options": {
    "redirect": {
      "follow": true,
      "maxRedirects": 5
    },
    "timeout": 10000
  }
}

// Handling pagination
{
  "url": "https://api.example.com/users",
  "method": "GET",
  "authentication": "None",
  "options": {
    "qs": {
      "page": "={{ $parameter.page || 1 }}",
      "limit": 100
    }
  }
}

OAuth Authentication

javascript
// OAuth2 Configuration
{
  "authentication": "OAuth2",
  "oAuth2Api": "custom",
  "authUrl": "https://auth.example.com/oauth/authorize",
  "accessTokenUrl": "https://auth.example.com/oauth/token",
  "clientId": "your-client-id",
  "clientSecret": "your-client-secret",
  "scope": "read write",
  "authQueryParameters": "",
  "authentication": "body"
}

Webhook Response Node

javascript
// Webhook Response Node Configuration
{
  "respondWith": "json",
  "responseBody": "={{ { success: true, data: $json.processedData } }}",
  "options": {
    "responseCode": 200,
    "responseHeaders": {
      "X-Powered-By": "n8n"
    }
  }
}

Database Operations

Postgres Node

javascript
// Query execution
{
  "operation": "executeQuery",
  "query": "SELECT * FROM users WHERE status = $1 AND created_at > $2",
  "values": [
    "={{ $json.status }}",
    "={{ $json.date }}"
  ]
}

// Insert operation
{
  "operation": "insert",
  "table": "users",
  "columns": "firstName,lastName,email,createdAt",
  "values": [
    "={{ $json.first_name }}",
    "={{ $json.last_name }}",
    "={{ $json.email }}",
    "={{ new Date().toISOString() }}"
  ]
}

// Update operation
{
  "operation": "update",
  "table": "users",
  "updateKey": "id",
  "columns": "status,updatedAt",
  "values": [
    "active",
    "={{ new Date().toISOString() }}"
  ]
}

MongoDB Node

javascript
// Find documents
{
  "operation": "find",
  "collection": "users",
  "options": {
    "limit": 100,
    "sort": {
      "createdAt": -1
    }
  },
  "query": "={{ { status: $json.status } }}"
}

// Insert document
{
  "operation": "insertOne",
  "collection": "logs",
  "document": "={{ { 
    action: $json.action,
    userId: $json.userId,
    timestamp: new Date(),
    details: $json.details
  } }}"
}

// Update document
{
  "operation": "updateOne",
  "collection": "users",
  "filter": "={{ { _id: $json.userId } }}",
  "update": "={{ { 
    $set: { 
      status: $json.newStatus,
      updatedAt: new Date()
    } 
  } }}",
  "options": {
    "upsert": false
  }
}

File Operations

Read Binary Files Node

javascript
// Read Binary Files Node Configuration
{
  "filePath": "/data/reports/latest.pdf"
}

// Read multiple files with pattern
{
  "filePath": "/data/reports/*.csv"
}

Write Binary File Node

javascript
// Write Binary File Node Configuration
{
  "filePath": "={{ '/data/processed/' + $json.filename }}",
  "fileName": "={{ $json.filename }}",
  "binaryPropertyName": "data",
  "options": {
    "encoding": "utf8",
    "createParentPath": true
  }
}

CSV Node

javascript
// Parse CSV
{
  "operation": "parse",
  "options": {
    "headerRow": true,
    "delimiter": ",",
    "includeEmptyLines": false,
    "skipLines": 0
  }
}

// Create CSV
{
  "operation": "create",
  "options": {
    "headerRow": true,
    "delimiter": ",",
    "includeEmptyLines": false
  }
}

AI Integration

OpenAI Node

javascript
// Text completion
{
  "authentication": "apiKey",
  "apiKey": "{{ $node['Credentials'].json.openai_api_key }}",
  "operation": "completion",
  "model": "gpt-4",
  "options": {
    "prompt": "={{ 'Summarize the following text in 3 bullet points:\\n\\n' + $json.text }}",
    "maxTokens": 500,
    "temperature": 0.7,
    "topP": 1,
    "presencePenalty": 0,
    "frequencyPenalty": 0,
    "stop": []
  }
}

// Chat completion
{
  "authentication": "apiKey",
  "apiKey": "{{ $node['Credentials'].json.openai_api_key }}",
  "operation": "chatCompletion",
  "messages": "={{ [
    { role: 'system', content: 'You are a helpful assistant.' },
    { role: 'user', content: $json.userMessage }
  ] }}",
  "model": "gpt-4",
  "options": {
    "temperature": 0.7,
    "maxTokens": 1000
  }
}

Anthropic Node

javascript
// Claude message
{
  "authentication": "apiKey",
  "apiKey": "{{ $node['Credentials'].json.anthropic_api_key }}",
  "operation": "message",
  "model": "claude-3-opus-20240229",
  "messages": "={{ [
    { role: 'user', content: $json.userMessage }
  ] }}",
  "options": {
    "temperature": 0.7,
    "maxTokens": 1000
  }
}

AI Document Processing

javascript
// Document processing workflow
// 1. Read Binary Files Node (PDF)
// 2. PDF Extract Node
{
  "operation": "extractText"
}
// 3. Text Splitter Node
{
  "operation": "splitByCharacter",
  "options": {
    "chunkSize": 1000,
    "chunkOverlap": 200
  }
}
// 4. OpenAI Node (for each chunk)
{
  "operation": "chatCompletion",
  "messages": "={{ [
    { role: 'system', content: 'Extract key information from this document chunk.' },
    { role: 'user', content: $json.text }
  ] }}",
  "model": "gpt-4",
  "options": {
    "temperature": 0.3
  }
}
// 5. Merge Node (combine all extracted information)
// 6. OpenAI Node (final summary)
{
  "operation": "chatCompletion",
  "messages": "={{ [
    { role: 'system', content: 'Create a comprehensive summary of this document based on the extracted information.' },
    { role: 'user', content: $json.extractedInfo }
  ] }}",
  "model": "gpt-4",
  "options": {
    "temperature": 0.5
  }
}

Advanced Features

Subworkflows

javascript
// Execute Workflow Node Configuration
{
  "workflowId": 123,
  "options": {
    "waitForResponse": true
  }
}

// Passing data to subworkflow
{
  "workflowId": 123,
  "options": {
    "waitForResponse": true
  },
  "parameters": "={{ {
    userId: $json.id,
    action: 'process',
    data: $json.payload
  } }}"
}

Credentials Management

javascript
// Access credentials in HTTP Request Node
{
  "url": "https://api.example.com/data",
  "method": "GET",
  "authentication": "Basic Auth",
  "username": "={{ $credentials.username }}",
  "password": "={{ $credentials.password }}"
}

Webhook Authentication

javascript
// Webhook Node with Basic Auth
{
  "path": "secure-endpoint",
  "authentication": {
    "basicAuth": {
      "user": "admin",
      "password": "secret"
    }
  },
  "responseMode": "onReceived",
  "responseData": "firstEntryJson"
}

// Webhook Node with Custom Auth (Header)
{
  "path": "api-endpoint",
  "httpMethod": "POST",
  "authentication": {
    "customAuth": {
      "checkOn": "header",
      "name": "X-API-KEY",
      "value": "your-secret-api-key"
    }
  },
  "responseMode": "lastNode",
  "responseData": "firstEntryJson"
}

Rate Limiting

javascript
// Limit Node Configuration
{
  "maxConcurrency": 5,
  "options": {
    "batchSize": 10,
    "batchInterval": 1000
  }
}

Workflow Variables

javascript
// Set Variable Node
{
  "variableName": "totalAmount",
  "value": "={{ $json.amount }}"
}

// Get Variable Node
{
  "variableName": "totalAmount"
}

// Using variables in expressions
"={{ $vars.totalAmount * 1.1 }}" // Add 10% tax

Deployment and Production

Environment Variables

bash
# Set environment variables for production
export N8N_ENCRYPTION_KEY=your-production-key
export N8N_PROTOCOL=https
export N8N_HOST=n8n.yourdomain.com
export N8N_PORT=5678
export N8N_BASIC_AUTH_ACTIVE=true
export N8N_BASIC_AUTH_USER=admin
export N8N_BASIC_AUTH_PASSWORD=secure-password

# Database configuration
export DB_TYPE=postgresdb
export DB_POSTGRESDB_HOST=production-db.yourdomain.com
export DB_POSTGRESDB_PORT=5432
export DB_POSTGRESDB_DATABASE=n8n_prod
export DB_POSTGRESDB_USER=n8n_user
export DB_POSTGRESDB_PASSWORD=db-password

# Queue configuration
export QUEUE_BULL_REDIS_HOST=redis.yourdomain.com
export QUEUE_BULL_REDIS_PORT=6379

Docker Compose for Production

yaml
version: '3.8'

services:
  n8n:
    image: n8nio/n8n:latest
    restart: always
    ports:
      - "5678:5678"
    environment:
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - N8N_PROTOCOL=https
      - N8N_HOST=${N8N_HOST}
      - N8N_PORT=5678
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=${N8N_BASIC_AUTH_USER}
      - N8N_BASIC_AUTH_PASSWORD=${N8N_BASIC_AUTH_PASSWORD}
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=${DB_USER}
      - DB_POSTGRESDB_PASSWORD=${DB_PASSWORD}
      - QUEUE_BULL_REDIS_HOST=redis
      - QUEUE_BULL_REDIS_PORT=6379
      - EXECUTIONS_PROCESS=main
      - EXECUTIONS_MODE=queue
      - GENERIC_TIMEZONE=UTC
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      - postgres
      - redis

  postgres:
    image: postgres:14
    restart: always
    environment:
      - POSTGRES_DB=n8n
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d n8n"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    restart: always
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  n8n_data:
  postgres_data:
  redis_data:

Scaling with Multiple Workers

bash
# Main process (API, UI, Webhook)
export EXECUTIONS_PROCESS=main
export EXECUTIONS_MODE=queue

# Worker processes (execute workflows)
export EXECUTIONS_PROCESS=worker
export EXECUTIONS_MODE=queue

Backup and Restore

bash
# Export workflows
n8n export:workflow --all --output=workflows-backup.json

# Import workflows
n8n import:workflow --input=workflows-backup.json

# Backup credentials (encrypted)
n8n export:credentials --all --output=credentials-backup.json

# Import credentials
n8n import:credentials --input=credentials-backup.json --separate

Best Practices

Workflow Organization

  • Naming Convention: Use clear, descriptive names for workflows and nodes
  • Documentation: Add descriptions to workflows and complex nodes
  • Modularization: Break complex processes into subworkflows
  • Tags: Use tags to categorize and organize workflows
  • Version Control: Export important workflows regularly

Performance Optimization

  • Batch Processing: Use Split In Batches for large datasets
  • Pagination: Implement proper pagination for API calls
  • Caching: Use Set/Get Variable nodes to cache repeated data
  • Limit Concurrency: Use Limit node to prevent overwhelming external services
  • Database Efficiency: Write efficient queries and use indexes

Error Handling

  • Error Workflows: Create dedicated error handling workflows
  • Retry Mechanisms: Implement retry logic for transient failures
  • Validation: Validate data before processing
  • Logging: Log important events and errors
  • Notifications: Set up alerts for critical failures

Security

  • Credentials: Use the built-in credentials system instead of hardcoding
  • Environment Variables: Store sensitive information in environment variables
  • Authentication: Secure webhook endpoints with authentication
  • Access Control: Implement proper user permissions
  • Audit Logs: Monitor workflow executions and changes

Troubleshooting

Common Issues

Workflow Not Triggering

  • Cause: Incorrect trigger configuration, webhook URL not accessible, or scheduling issues
  • Solution: Verify trigger settings, check webhook accessibility, and confirm timezone settings

Node Execution Failures

  • Cause: Invalid data format, missing required fields, or API rate limits
  • Solution: Use Function nodes to validate and transform data, implement error handling, and add rate limiting

Performance Issues

  • Cause: Processing large datasets, inefficient queries, or resource constraints
  • Solution: Implement batch processing, optimize database queries, and scale n8n deployment

Authentication Errors

  • Cause: Expired credentials, incorrect API keys, or OAuth token issues
  • Solution: Update credentials, verify API key permissions, and refresh OAuth tokens

This comprehensive n8n cheat sheet provides everything needed to build sophisticated workflow automations. From basic setup to advanced production deployment patterns, use these examples and best practices to create powerful, flexible automation workflows with n8n's versatile platform.