AutomationFlowsAI & RAG › Ecommerce ETL KPI Postgres

Ecommerce ETL KPI Postgres

22-ecommerce-etl-kpi-postgres. Uses schedule, httpRequest, postgres, slack. Scheduled trigger; 6 nodes.

Cron / scheduled trigger★★★★☆ complexity6 nodesScheduleHTTP RequestPostgresSlack
AI & RAG Trigger: Cron / scheduled Nodes: 6 Complexity: ★★★★☆ Added:

This workflow follows the HTTP Request → Postgres recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "22-ecommerce-etl-kpi-postgres",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "days",
              "triggerAt": "00:00"
            }
          ]
        }
      },
      "id": "b2c3d4e5-1111-4444-8888-000000000001",
      "name": "Schedule",
      "type": "n8n-nodes-base.schedule",
      "typeVersion": 1,
      "position": [
        240,
        400
      ]
    },
    {
      "parameters": {
        "url": "https://jsonplaceholder.typicode.com/posts",
        "method": "GET",
        "options": {}
      },
      "id": "b2c3d4e5-2222-4444-8888-000000000002",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.1,
      "position": [
        460,
        400
      ],
      "notes": "\u0634\u0628\u06cc\u0647\u200c\u0633\u0627\u0632\u06cc \u062f\u0631\u06cc\u0627\u0641\u062a \u062f\u0627\u062f\u0647\u200c\u0647\u0627\u06cc \u0641\u0631\u0648\u0634 \u0627\u0632 API \u0641\u0631\u0648\u0634\u06af\u0627\u0647. \u062f\u0631 \u0645\u062d\u06cc\u0637 \u0648\u0627\u0642\u0639\u06cc\u060c URL \u0648 \u0647\u062f\u0631\u0647\u0627\u06cc \u0627\u062d\u0631\u0627\u0632 \u0647\u0648\u06cc\u062a \u0631\u0627 \u062c\u0627\u06cc\u06af\u0632\u06cc\u0646 \u06a9\u0646\u06cc\u062f."
    },
    {
      "parameters": {
        "jsCode": "// \u0645\u062d\u0627\u0633\u0628\u0647 KPI\u0647\u0627\u06cc \u0641\u0631\u0648\u0634 \u0627\u0632 \u0644\u06cc\u0633\u062a \u0622\u06cc\u062a\u0645\u200c\u0647\u0627\nconst items = $input.all();\n\n// \u0634\u0628\u06cc\u0647\u200c\u0633\u0627\u0632\u06cc \u0645\u0642\u062f\u0627\u0631 \u0641\u0631\u0648\u0634 \u0628\u0631\u0627\u06cc \u0647\u0631 \u0622\u06cc\u062a\u0645 (\u062f\u0631 \u0648\u0627\u0642\u0639\u06cc\u062a \u0627\u0632 \u0641\u06cc\u0644\u062f amount \u06cc\u0627 price \u062f\u0627\u062f\u0647\u200c\u0647\u0627\u06cc \u0648\u0627\u0642\u0639\u06cc \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc\u200c\u0634\u0648\u062f)\nlet totalRevenue = 0;\nitems.forEach(item => {\n  // \u0641\u0631\u0636 \u0645\u06cc\u200c\u06a9\u0646\u06cc\u0645 \u0647\u0631 \u0622\u06cc\u062a\u0645 \u0646\u0645\u0627\u062f \u06cc\u06a9 \u0633\u0641\u0627\u0631\u0634 \u0628\u0627 \u0645\u0642\u062f\u0627\u0631 \u062a\u0635\u0627\u062f\u0641\u06cc \u0628\u06cc\u0646 100 \u062a\u0627 1000 \u062f\u0644\u0627\u0631 \u0627\u0633\u062a\n  const mockAmount = Math.floor(Math.random() * 900) + 100;\n  totalRevenue += mockAmount;\n});\n\nconst totalCount = items.length;\nconst aov = totalCount > 0 ? (totalRevenue / totalCount).toFixed(2) : 0;\nconst today = new Date().toISOString().split('T')[0];\n\nreturn [{\n  json: {\n    report_date: today,\n    total_revenue: totalRevenue,\n    total_orders: totalCount,\n    average_order_value: parseFloat(aov)\n  }\n}];"
      },
      "id": "b2c3d4e5-3333-4444-8888-000000000003",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        680,
        400
      ]
    },
    {
      "parameters": {
        "operation": "upsert",
        "table": {
          "__rl": true,
          "value": "daily_kpi",
          "mode": "list",
          "cachedResultName": "daily_kpi"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "report_date": "={{ $json.report_date }}",
            "total_revenue": "={{ $json.total_revenue }}",
            "total_orders": "={{ $json.total_orders }}",
            "average_order_value": "={{ $json.average_order_value }}"
          },
          "matchingColumns": [
            "report_date"
          ],
          "schema": [
            {
              "id": "report_date",
              "displayName": "report_date",
              "required": false,
              "defaultMatch": true,
              "canBeUsedToMatch": true,
              "type": "string"
            },
            {
              "id": "total_revenue",
              "displayName": "total_revenue",
              "required": false,
              "defaultMatch": false,
              "canBeUsedToMatch": false,
              "type": "number"
            },
            {
              "id": "total_orders",
              "displayName": "total_orders",
              "required": false,
              "defaultMatch": false,
              "canBeUsedToMatch": false,
              "type": "number"
            },
            {
              "id": "average_order_value",
              "displayName": "average_order_value",
              "required": false,
              "defaultMatch": false,
              "canBeUsedToMatch": false,
              "type": "number"
            }
          ]
        },
        "options": {}
      },
      "id": "b2c3d4e5-4444-4444-8888-000000000004",
      "name": "PostgreSQL",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        900,
        400
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "cond1",
              "leftValue": "={{ $json.total_revenue }}",
              "rightValue": 5000,
              "operator": {
                "type": "number",
                "operation": "gte"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "b2c3d4e5-5555-4444-8888-000000000005",
      "name": "IF",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1120,
        400
      ]
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": {
          "__rl": true,
          "value": "C0987654321",
          "mode": "list",
          "cachedResultName": "management-reports"
        },
        "text": "\ud83d\udcc8 *Daily Sales Target Achieved!*\n\n\ud83d\udcc5 *Date:* {{ $json.report_date }}\n\ud83d\udcb0 *Total Revenue:* ${{ $json.total_revenue }}\n\ud83d\uded2 *Total Orders:* {{ $json.total_orders }}\n\ud83d\udcca *Average Order Value:* ${{ $json.average_order_value }}\n\nGreat job team! \ud83d\ude80",
        "otherOptions": {}
      },
      "id": "b2c3d4e5-6666-4444-8888-000000000006",
      "name": "Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.2,
      "position": [
        1340,
        320
      ],
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Schedule": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code": {
      "main": [
        [
          {
            "node": "PostgreSQL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "PostgreSQL": {
      "main": [
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF": {
      "main": [
        [
          {
            "node": "Slack",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "all"
  },
  "id": "22-ecommerce-etl-kpi-postgres",
  "tags": []
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

22-ecommerce-etl-kpi-postgres. Uses schedule, httpRequest, postgres, slack. Scheduled trigger; 6 nodes.

Source: https://github.com/kooroosh1363/agentic-automation-lab/blob/main/22-ecommerce-etl-kpi-postgres/workflow.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

This n8n template builds an automated daily news digest powered by Claude AI.

Postgres, HTTP Request, Chain Llm +3
AI & RAG

Automates sales data analysis and strategic insight generation for sales managers and strategists needing actionable intelligence. Fetches multi-source data from sales, marketing, and financial system

HTTP Request, Agent, OpenAI Chat +6
AI & RAG

Scheduled runs collect data from oil markets, global shipping movements, news sources, and official reports. The system performs statistical checks to detect anomalies and volatility shifts. An AI-dri

HTTP Request, Agent, Gmail +3
AI & RAG

This workflow automates end-to-end patient care coordination by monitoring appointment schedules, clinical events, and care milestones while orchestrating personalized communications across multiple c

HTTP Request, Agent, OpenAI Chat +5
AI & RAG

Business Post Pipeline. Uses postgres, httpRequest, agent, lmChatGoogleGemini. Scheduled trigger; 30 nodes.

Postgres, HTTP Request, Agent +4