AutomationFlowsData & Sheets › Error Handling System with Postgresql Logging and Rate-limited Notifications

Error Handling System with Postgresql Logging and Rate-limited Notifications

ByDavi Saranszky Mesquita @frkr on n8n.io

Most of the time, it’s necessary to log all errors that occur. However, in some cases, a scheduled task or service consuming excessive resources might trigger a surge of errors.

Event trigger★★★★☆ complexity16 nodesError TriggerPostgresEmail SendPushoverExecute Workflow Trigger
Data & Sheets Trigger: Event Nodes: 16 Complexity: ★★★★☆ Added:
Error Handling System with Postgresql Logging and Rate-limited Notifications — n8n workflow card showing Error Trigger, Postgres, Email Send integration

This workflow corresponds to n8n.io template #3882 — we link there as the canonical source.

This workflow follows the Emailsend → 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
{
  "id": "YybYYc430rmZWJPJ",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Log errors and avoid sending too many emails",
  "tags": [
    {
      "id": "7YoU4oTsaGGEtWJj",
      "name": "sample",
      "createdAt": "2025-01-31T16:41:27.407Z",
      "updatedAt": "2025-01-31T16:41:27.407Z"
    }
  ],
  "nodes": [
    {
      "id": "0e44df4c-00d2-4545-89ae-844a590de369",
      "name": "Error Trigger",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        -1200,
        90
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "7101542a-5146-4917-a1f2-13686cad197e",
      "name": "Insert Log",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -980,
        40
      ],
      "parameters": {
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "N8Err",
          "cachedResultName": "N8Err"
        },
        "schema": {
          "__rl": true,
          "mode": "name",
          "value": "p1gq6ljdsam3x1m"
        },
        "columns": {
          "value": {
            "URL": "={{ $json.execution.url }}",
            "json": "={{ JSON.stringify($json) }}",
            "Stack": "={{ $json.execution.error.stack }}",
            "title": "={{ $json.workflow.name }}",
            "Message": "={{ $json.execution.error.message }}",
            "LastNode": "={{ $json.execution.lastNodeExecuted }}",
            "created_at": "={{ $now }}"
          },
          "schema": [
            {
              "id": "id",
              "type": "number",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "id",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "created_at",
              "type": "dateTime",
              "display": true,
              "required": false,
              "displayName": "created_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "updated_at",
              "type": "dateTime",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "updated_at",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "created_by",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "created_by",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "updated_by",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "updated_by",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "nc_order",
              "type": "number",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "nc_order",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "title",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Stack",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Stack",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "json",
              "type": "object",
              "display": true,
              "required": false,
              "displayName": "json",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Message",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Message",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "LastNode",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "LastNode",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "id"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "8fb1201c-353e-466c-8d08-fd969e6b10b1",
      "name": "Count for 5 minutes",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -980,
        -210
      ],
      "parameters": {
        "query": "SELECT count(*) FROM p1gq6ljdsam3x1m.\"N8Err\" where created_at >= $1;\n",
        "options": {
          "queryReplacement": "={{ $now.minus(5, 'minutes').toString() }}"
        },
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "89f836dc-8141-4c20-a758-bf7ff261a87b",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2260,
        -300
      ],
      "parameters": {
        "color": 5,
        "width": 820,
        "height": 1140,
        "content": "# Log errors and avoid sending too many emails\n\n## Use case\n\nMost of the time, it\u2019s necessary to log all errors that occur. However, in some cases, a scheduled task or service consuming excessive resources might trigger a surge of errors.\n\nTo address this, we can log all errors but limit alerts to a maximum of one notification every 5 minutes.\n\n## What this workflow does\n\nThis workflow can be configured to receive error events, or you can integrate it **before your own error-handling logic.**  \n\nIf used as the **primary error handler**, note that this flow will **only add a database log entry** and take no further action. You\u2019ll need to add your own alerts (e.g., email or push notifications). Below is an example of a notification setup I prefer to use.  \n\nAt the end, there\u2019s an **error cleanup** option. This feature is particularly useful in development environments.  \n\nIf you already have an error-handling workflow, you can call this one as a **sub-workflow**. Its final steps include cleanup logic to reset the execution state and terminate the workflow.\n\n## Setup\n\n**Verify all Postgres nodes and credentials when using the 'Error Handling Sample'**\n\n## How to adjust it to your needs\n\n1) You can set this workflow as a sub-workflow within your existing error-handling setup.\n\n2) Alternatively, you can add the \"Error Handling Sample\" at the end of this workflow, which sends email and push notifications.\n\nConfiguration Requirements:\n\n\u26a0\ufe0f You must create a database table for this to work!\n\n\n\nDDL of this sample:\n\ncreate table p1gq6ljdsam3x1m.\"N8Err\"\n(\n    id         serial\n        primary key,\n    created_at timestamp,\n    updated_at timestamp,\n    created_by varchar,\n    updated_by varchar,\n    nc_order   numeric,\n    title      text,\n    \"URL\"      text,\n    \"Stack\"    text,\n    json       json,\n    \"Message\"  text,\n    \"LastNode\" text\n);\n\nalter table p1gq6ljdsam3x1m.\"N8Err\"\n    owner to postgres;\n\ncreate index \"N8Err_order_idx\"\n    on p1gq6ljdsam3x1m.\"N8Err\" (nc_order);\n\nby Davi Saranszky Mesquita\nhttps://www.linkedin.com/in/mesquitadavi/"
      },
      "typeVersion": 1
    },
    {
      "id": "fba7fec5-5285-46bd-9cc7-270b7dcc8c5f",
      "name": "Principal E-Mail",
      "type": "n8n-nodes-base.emailSend",
      "onError": "continueErrorOutput",
      "disabled": true,
      "position": [
        -980,
        350
      ],
      "parameters": {
        "text": "={{ $(\"Error Trigger\").item.json.execution.url }}\n\n{{ $(\"Error Trigger\").item.json.execution.lastNodeExecuted }}\n\n{{ $(\"Error Trigger\").item.json.execution.error.message }}\n{{ $(\"Error Trigger\").item.json.execution.error.stack }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "=Erro -  {{ $(\"Error Trigger\").item.json.workflow.name }}",
        "toEmail": "user@example.com",
        "fromEmail": "user@example.com",
        "emailFormat": "text"
      },
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "979d0e82-42e8-450a-95b1-3c204ad61a50",
      "name": "Fallback E-Mail",
      "type": "n8n-nodes-base.emailSend",
      "disabled": true,
      "position": [
        -760,
        350
      ],
      "parameters": {
        "text": "={{ $(\"Error Trigger\").item.json.execution.url }}\n\n{{ $(\"Error Trigger\").item.json.execution.lastNodeExecuted }}\n\n{{ $(\"Error Trigger\").item.json.execution.error.message }}\n{{ $(\"Error Trigger\").item.json.execution.error.stack }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "=Erro -  {{ $(\"Error Trigger\").item.json.workflow.name }}",
        "toEmail": "user@example.com",
        "fromEmail": "user@example.com",
        "emailFormat": "text"
      },
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "6c073c03-e00e-45b1-8f14-faa29fd58472",
      "name": "Push mobile notification",
      "type": "n8n-nodes-base.pushover",
      "disabled": true,
      "position": [
        -980,
        550
      ],
      "parameters": {
        "message": "={{ $(\"Error Trigger\").item.json.workflow.name }} - {{ $(\"Error Trigger\").item.json.execution.url }}\n\n{{ $(\"Error Trigger\").item.json.execution.lastNodeExecuted }}\n\n{{ $(\"Error Trigger\").item.json.execution.error.message }}\n{{ $(\"Error Trigger\").item.json.execution.error.stack }}",
        "userKey": "=u4RMqXQR9EFdeSQBfaL1riBy1Qd953",
        "additionalFields": {}
      },
      "credentials": {
        "pushoverApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4ca939e4-dcb1-40bd-b5eb-4cd00cb403fb",
      "name": "Truncate Log Database",
      "type": "n8n-nodes-base.postgres",
      "position": [
        -980,
        810
      ],
      "parameters": {
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "N8Err",
          "cachedResultName": "N8Err"
        },
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "p1gq6ljdsam3x1m",
          "cachedResultName": "p1gq6ljdsam3x1m"
        },
        "options": {},
        "operation": "deleteTable",
        "restartSequences": true
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "1eaf67ca-fb77-4b76-8ee3-ae65d4b79182",
      "name": "Sometimes... just cleanup",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -1200,
        810
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "01e5a7dd-41a2-43f1-bbf5-241e6791cf18",
      "name": "Call this Sample - Prepend to your error catcher",
      "type": "n8n-nodes-base.executeWorkflow",
      "disabled": true,
      "position": [
        -1200,
        450
      ],
      "parameters": {
        "options": {},
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": ""
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "4386788d-5f10-468a-8a02-cff45a4a7ed5",
      "name": "See below to prepend this at your error handling",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        -1200,
        -260
      ],
      "parameters": {
        "inputSource": "passthrough"
      },
      "typeVersion": 1.1
    },
    {
      "id": "d6aed974-4a36-4edd-809d-867a95d0f6ef",
      "name": "If there is no logs in 5 minutes",
      "type": "n8n-nodes-base.if",
      "position": [
        -760,
        -210
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a17b915d-f581-4774-a78a-48bc386aebc9",
              "operator": {
                "type": "number",
                "operation": "lte"
              },
              "leftValue": "={{ $json.count }}",
              "rightValue": 0
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "3c49f611-f1a6-409a-a4c6-903dadb27165",
      "name": "CleanUp execution. See below if you will prepend this workflow",
      "type": "n8n-nodes-base.code",
      "position": [
        -540,
        -10
      ],
      "parameters": {
        "jsCode": "return [];"
      },
      "typeVersion": 2
    },
    {
      "id": "192443fc-c032-4815-acc7-c8cf6040cc34",
      "name": "Insert your error handling logic after this",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -540,
        -260
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "2f87907f-816f-4054-8517-bb713a203131",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1350,
        250
      ],
      "parameters": {
        "width": 840,
        "height": 460,
        "content": "# Error handling sample\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b173898f-d1d8-4f83-b7b7-ba52cab7651e",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1610,
        630
      ],
      "parameters": {
        "width": 1140,
        "height": 340,
        "content": "# Database Cleanup: Useful in DEV, but DO NOT run in production"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "executionOrder": "v1",
    "saveManualExecutions": false,
    "saveExecutionProgress": false,
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "none"
  },
  "versionId": "07c6795a-f906-4e22-a15a-4f1984e540a3",
  "connections": {
    "Insert Log": {
      "main": [
        [
          {
            "node": "CleanUp execution. See below if you will prepend this workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Error Trigger": {
      "main": [
        [
          {
            "node": "Insert Log",
            "type": "main",
            "index": 0
          },
          {
            "node": "Count for 5 minutes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Principal E-Mail": {
      "main": [
        [],
        [
          {
            "node": "Fallback E-Mail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Count for 5 minutes": {
      "main": [
        [
          {
            "node": "If there is no logs in 5 minutes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sometimes... just cleanup": {
      "main": [
        [
          {
            "node": "Truncate Log Database",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If there is no logs in 5 minutes": {
      "main": [
        [
          {
            "node": "Insert your error handling logic after this",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "CleanUp execution. See below if you will prepend this workflow",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Call this Sample - Prepend to your error catcher": {
      "main": [
        [
          {
            "node": "Principal E-Mail",
            "type": "main",
            "index": 0
          },
          {
            "node": "Push mobile notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "See below to prepend this at your error handling": {
      "main": [
        [
          {
            "node": "Insert Log",
            "type": "main",
            "index": 0
          },
          {
            "node": "Count for 5 minutes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CleanUp execution. See below if you will prepend this workflow": {
      "main": [
        []
      ]
    }
  }
}

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

Most of the time, it’s necessary to log all errors that occur. However, in some cases, a scheduled task or service consuming excessive resources might trigger a surge of errors.

Source: https://n8n.io/workflows/3882/ — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

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

Data & Sheets

Log errors and avoid sending too many emails. Uses errorTrigger, postgres, stickyNote, emailSend. Event-driven trigger; 16 nodes.

Error Trigger, Postgres, Email Send +2
Data & Sheets

Subflow — PDF Generate. Uses executeWorkflowTrigger, httpRequest, postgres, errorTrigger. Event-driven trigger; 11 nodes.

Execute Workflow Trigger, HTTP Request, Postgres +1
Data & Sheets

Agendamiento_v2. Uses n8n-nodes-evolution-api, redis, httpRequest, executeWorkflowTrigger. Event-driven trigger; 59 nodes.

N8N Nodes Evolution Api, Redis, HTTP Request +3
Data & Sheets

Cancelacion_v2. Uses executeWorkflowTrigger, redis, httpRequest, n8n-nodes-evolution-api. Event-driven trigger; 46 nodes.

Execute Workflow Trigger, Redis, HTTP Request +3
Data & Sheets

Keep your customer knowledge base up to date with this n8n automation template. The workflow connects Zendesk with Google Sheets, automatically fetching tickets tagged as “howto,” enriching them with

Error Trigger, Zendesk, Google Sheets +1