mcpField
N
n8n-patterns

n8n-patterns

github.com/mindmorass開発281 回インストール37 週間前に更新
リポジトリ

n8n-patterns について

n8n-patternsは、n8nで自動化ワークフローを構築する人向けの実践ガイドです。トリガー、データ処理、エラー対応、再利用可能なサブワークフロー、デプロイのパターンを扱います。

主な機能

  1. 01Webhook・スケジュール・アプリのトリガー
  2. 02データ変換と制御フロー
  3. 03エラー処理とリトライのパターン
  4. 04サブワークフローとREST API呼び出し
  5. 05認証情報管理とセルフホスト設定

活用シーン

  1. 01イベント駆動または定期実行の設計
  2. 02APIページネーションとデータ変換
  3. 03ワークフローへのエラー処理とリトライ追加
  4. 04再利用可能なサブワークフローの設計

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mindmorass/reflex --skill n8n-patterns

インストール後、Claude Code で/n8n-patternsを入力して読み込まれたか確認します。

詳細

n8n ワークフローパターン

オープンソースのワークフロー自動化ツールである n8n を使って、堅牢なワークフロー自動化を構築しましょう。

概要

n8n は、アプリやサービスを連携するセルフホスト可能なワークフロー自動化プラットフォームです。主な機能:

  • 400 以上の連携機能を備えたビジュアルワークフロービルダー
  • セルフホストまたはクラウドへのデプロイ
  • カスタムロジック用のコードノード(JavaScript/Python)
  • リアルタイム自動化のための Webhook トリガー
  • モジュール設計のためのサブワークフロー

コアコンセプト

ワークフローの構造
┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Trigger   │───▶│    Node     │───▶│   Output    │
│  (Start)    │    │  (Process)  │    │  (Action)   │
└─────────────┘    └─────────────┘    └─────────────┘
ノードの種類
種類目的例
トリガーワークフローを開始Webhook、スケジュール、アプリトリガー
アクション操作を実行HTTP Request、データベース、メール
変換データを変更Set、Code、IF、Switch
フロー実行を制御Merge、Split、Wait、Loop

トリガーパターン

Webhook トリガー
{
  "nodes": [
    {
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "httpMethod": "POST",
        "path": "my-webhook",
        "responseMode": "responseNode",
        "options": {
          "rawBody": true
        }
      }
    }
  ]
}

ベストプラクティス:

  • カスタム応答には responseNode を使用します
  • 署名の検証には rawBody を有効にします
  • 認証を追加します(Header Auth、Basic Auth)
スケジュールトリガー
{
  "name": "Schedule Trigger",
  "type": "n8n-nodes-base.scheduleTrigger",
  "parameters": {
    "rule": {
      "interval": [
        {
          "field": "cronExpression",
          "expression": "0 9 * * 1-5"
        }
      ]
    }
  }
}

一般的なスケジュール:

  • 0 * * * * - 毎時
  • 0 9 * * 1-5 - 平日の午前 9 時
  • 0 0 * * 0 - 毎週日曜日の午前 0 時
  • */15 * * * * - 15 分ごと
アプリトリガー(ポーリング)
{
  "name": "GitHub Trigger",
  "type": "n8n-nodes-base.githubTrigger",
  "parameters": {
    "owner": "{{$env.GITHUB_OWNER}}",
    "repository": "{{$env.GITHUB_REPO}}",
    "events": ["issues", "pull_request"]
  }
}

データ変換パターン

Set ノード(データを変換)
{
  "name": "Transform Data",
  "type": "n8n-nodes-base.set",
  "parameters": {
    "mode": "manual",
    "duplicateItem": false,
    "assignments": {
      "assignments": [
        {
          "name": "fullName",
          "value": "={{ $json.firstName }} {{ $json.lastName }}",
          "type": "string"
        },
        {
          "name": "timestamp",
          "value": "={{ DateTime.now().toISO() }}",
          "type": "string"
        }
      ]
    }
  }
}
Code ノード(JavaScript)
// Process items with custom logic
const results = [];

for (const item of $input.all()) {
  const data = item.json;

  // Transform data
  results.push({
    json: {
      id: data.id,
      processed: true,
      score: calculateScore(data),
      timestamp: new Date().toISOString()
    }
  });
}

function calculateScore(data) {
  return data.value * 0.8 + data.bonus * 0.2;
}

return results;
Code ノード(Python)
# Enable Python in n8n settings
import json
from datetime import datetime

results = []

for item in _input.all():
    data = item.json

    # Transform data
    results.append({
        "json": {
            "id": data.get("id"),
            "processed": True,
            "timestamp": datetime.now().isoformat()
        }
    })

return results

制御フローパターン

IF ノード(条件分岐)
{
  "name": "Check Status",
  "type": "n8n-nodes-base.if",
  "parameters": {
    "conditions": {
      "options": {
        "caseSensitive": true,
        "leftValue": "",
        "typeValidation": "strict"
      },
      "conditions": [
        {
          "leftValue": "={{ $json.status }}",
          "rightValue": "active",
          "operator": {
            "type": "string",
            "operation": "equals"
          }
        }
      ],
      "combinator": "and"
    }
  }
}
Switch ノード(複数分岐)
{
  "name": "Route by Type",
  "type": "n8n-nodes-base.switch",
  "parameters": {
    "mode": "rules",
    "rules": {
      "values": [
        {
          "outputKey": "order",
          "conditions": {
            "conditions": [
              {
                "leftValue": "={{ $json.type }}",
                "rightValue": "order",
                "operator": { "type": "string", "operation": "equals" }
              }
            ]
          }
        },
        {
          "outputKey": "refund",
          "conditions": {
            "conditions": [
              {
                "leftValue": "={{ $json.type }}",
                "rightValue": "refund",
                "operator": { "type": "string", "operation": "equals" }
              }
            ]
          }
        }
      ]
    },
    "fallbackOutput": "extra"
  }
}
アイテムをループ
{
  "name": "Loop Over Items",
  "type": "n8n-nodes-base.splitInBatches",
  "parameters": {
    "batchSize": 10,
    "options": {
      "reset": false
    }
  }
}
Merge ノード(データを結合)
{
  "name": "Merge Results",
  "type": "n8n-nodes-base.merge",
  "parameters": {
    "mode": "combine",
    "mergeByFields": {
      "values": [
        {
          "field1": "id",
          "field2": "userId"
        }
      ]
    },
    "options": {}
  }
}

エラー処理パターン

Error Trigger を使った Try/Catch
{
  "nodes": [
    {
      "name": "Error Trigger",
      "type": "n8n-nodes-base.errorTrigger",
      "parameters": {}
    },
    {
      "name": "Send Alert",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "channel": "#alerts",
        "text": "Workflow failed: {{ $json.workflow.name }}\nError: {{ $json.execution.error.message }}"
      }
    }
  ]
}
失敗時に再試行
{
  "name": "HTTP Request",
  "type": "n8n-nodes-base.httpRequest",
  "parameters": {
    "url": "https://api.example.com/data",
    "options": {}
  },
  "retryOnFail": true,
  "maxTries": 3,
  "waitBetweenTries": 1000
}
Stop and Error ノード
{
  "name": "Validation Failed",
  "type": "n8n-nodes-base.stopAndError",
  "parameters": {
    "errorMessage": "Invalid input: {{ $json.error }}"
  }
}

サブワークフローパターン

Execute Workflow ノード
{
  "name": "Process Order",
  "type": "n8n-nodes-base.executeWorkflow",
  "parameters": {
    "source": "database",
    "workflowId": "order-processing-workflow-id",
    "mode": "each",
    "options": {
      "waitForSubWorkflow": true
    }
  }
}

ベストプラクティス:

  • 再利用可能なロジックにはサブワークフローを使用します
  • ワークフロー間で渡すデータは最小限にします
  • 必要に応じて waitForSubWorkflow を設定します
  • 整理にはワークフロータグを使用します

HTTP Request パターン

REST API 呼び出し
{
  "name": "API Request",
  "type": "n8n-nodes-base.httpRequest",
  "parameters": {
    "method": "POST",
    "url": "https://api.example.com/v1/resource",
    "authentication": "predefinedCredentialType",
    "nodeCredentialType": "httpHeaderAuth",
    "sendHeaders": true,
    "headerParameters": {
      "parameters": [
        {
          "name": "Content-Type",
          "value": "application/json"
        }
      ]
    },
    "sendBody": true,
    "bodyParameters": {
      "parameters": [
        {
          "name": "data",
          "value": "={{ JSON.stringify($json) }}"
        }
      ]
    },
    "options": {
      "timeout": 30000,
      "response": {
        "response": {
          "fullResponse": false,
          "responseFormat": "json"
        }
      }
    }
  }
}
ページネーションパターン
// Code node for API pagination
const allResults = [];
let page = 1;
let hasMore = true;

while (hasMore) {
  const response = await this.helpers.httpRequest({
    method: 'GET',
    url: `https://api.example.com/items?page=${page}&limit=100`,
    headers: {
      'Authorization': `Bearer ${$env.API_TOKEN}`
    }
  });

  allResults.push(...response.data);
  hasMore = response.hasNextPage;
  page++;

  // Rate limiting
  await new Promise(r => setTimeout(r, 100));
}

return allResults.map(item => ({ json: item }));

認証情報の管理

環境変数
// Access in expressions
{{ $env.API_KEY }}
{{ $env.DATABASE_URL }}

// Access in Code node
const apiKey = $env.API_KEY;
認証情報の種類
種類用途
httpBasicAuthBasic 認証
httpHeaderAuthヘッダー内の API キー
oAuth2ApiOAuth 2.0 フロー
httpQueryAuthクエリ文字列内の API キー

セルフホスティングパターン

Docker Compose
version: '3.8'

services:
  n8n:
    image: n8nio/n8n:latest
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=${N8N_USER}
      - N8N_BASIC_AUTH_PASSWORD=${N8N_PASSWORD}
      - N8N_HOST=${N8N_HOST}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_URL=https://${N8N_HOST}/
      - GENERIC_TIMEZONE=UTC
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=${POSTGRES_USER}
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=168
    volumes:
      - n8n_data:/home/node/.n8n
    depends_on:
      - postgres

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

volumes:
  n8n_data:
  postgres_data:
環境変数(.env)
# n8n Configuration
N8N_HOST=n8n.example.com
N8N_USER=admin
N8N_PASSWORD=secure-password-here
N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)

# Database
POSTGRES_USER=n8n
POSTGRES_PASSWORD=secure-db-password

# Optional: Queue mode for scaling
EXECUTIONS_MODE=queue
QUEUE_BULL_REDIS_HOST=redis
キューモード(スケーリング)
# docker-compose.queue.yml
services:
  n8n:
    environment:
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
      - QUEUE_HEALTH_CHECK_ACTIVE=true

  n8n-worker:
    image: n8nio/n8n:latest
    command: worker
    environment:
      - EXECUTIONS_MODE=queue
      - QUEUE_BULL_REDIS_HOST=redis
    deploy:
      replicas: 3

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data

一般的なワークフローテンプレート

Webhook からデータベースへ
{
  "name": "Webhook to Database",
  "nodes": [
    {
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "httpMethod": "POST",
        "path": "ingest",
        "responseMode": "responseNode"
      }
    },
    {
      "name": "Validate",
      "type": "n8n-nodes-base.if",
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "leftValue": "={{ $json.id }}",
              "rightValue": "",
              "operator": { "type": "string", "operation": "notEmpty" }
            }
          ]
        }
      }
    },
    {
      "name": "Insert",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "insert",
        "table": "events",
        "columns": "id,type,data,created_at"
      }
    },
    {
      "name": "Success Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { \"success\": true, \"id\": $json.id } }}"
      }
    }
  ]
}
スケジュールされた同期
{
  "name": "Daily Data Sync",
  "nodes": [
    {
      "name": "Schedule",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [{ "field": "cronExpression", "expression": "0 2 * * *" }]
        }
      }
    },
    {
      "name": "Fetch Source",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://api.source.com/data",
        "authentication": "predefinedCredentialType"
      }
    },
    {
      "name": "Transform",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "return $input.all().map(item => ({ json: { ...item.json, synced_at: new Date().toISOString() } }));"
      }
    },
    {
      "name": "Upsert Destination",
      "type": "n8n-nodes-base.postgres",
      "parameters": {
        "operation": "upsert",
        "table": "synced_data"
      }
    }
  ]
}
イベント駆動型通知
{
  "name": "Alert Pipeline",
  "nodes": [
    {
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "parameters": { "path": "alert" }
    },
    {
      "name": "Route by Severity",
      "type": "n8n-nodes-base.switch",
      "parameters": {
        "rules": {
          "values": [
            { "outputKey": "critical", "conditions": { "conditions": [{ "leftValue": "={{ $json.severity }}", "rightValue": "critical" }] } },
            { "outputKey": "warning", "conditions": { "conditions": [{ "leftValue": "={{ $json.severity }}", "rightValue": "warning" }] } }
          ]
        }
      }
    },
    {
      "name": "Page On-Call",
      "type": "n8n-nodes-base.pagerDuty"
    },
    {
      "name": "Slack Alert",
      "type": "n8n-nodes-base.slack"
    }
  ]
}

式のチートシート

式説明
{{ $json.field }}現在のアイテムからフィールドにアクセス
{{ $json["field-name"] }}特殊文字を含むフィールドにアクセス
{{ $('NodeName').item.json.field }}特定のノードのデータにアクセス
{{ $input.first().json }}最初の入力アイテム
{{ $input.all() }}すべての入力アイテム
{{ $env.VAR_NAME }}環境変数
{{ $now }}現在の日時
{{ $today }}今日の日付
{{ $runIndex }}現在の実行ランインデックス
{{ $itemIndex }}現在のアイテムインデックス
{{ $workflow.id }}ワークフロー ID
{{ $execution.id }}実行 ID

Luxon DateTime の例

// n8n uses Luxon for dates
{{ $now.toISO() }}                    // ISO format
{{ $now.toFormat('yyyy-MM-dd') }}     // Custom format
{{ $now.plus({ days: 7 }).toISO() }}  // Add 7 days
{{ $now.startOf('month').toISO() }}   // Start of month
{{ DateTime.fromISO($json.date) }}    // Parse ISO string

ベストプラクティス

  1. 命名:動詞+名詞を使った説明的なノード名を付けます
  2. エラー処理:必ずエラーワークフローを追加します
  3. 認証情報:シークレットをハードコードしないでください
  4. バッチ処理:大規模なデータセットには splitInBatches を使用します
  5. タイムアウト:HTTP ノードには適切なタイムアウトを設定します
  6. ログ記録:デバッグには Code ノードで console.log を使用します
  7. テスト:有効化する前に手動実行します
  8. バージョン管理:ワークフローを JSON として git にエクスポートします
  9. ドキュメント:複雑なロジックには付箋を追加します
  10. モジュール設計:再利用性を高めるためにサブワークフローを使用します

デバッグのヒント

// In Code node - log to n8n console
console.log('Debug:', JSON.stringify($json, null, 2));

// Return debug info
return [{
  json: {
    debug: true,
    input: $json,
    env: $env.NODE_ENV,
    timestamp: new Date().toISOString()
  }
}];

Resources

コメント