AutomationFlowsData & Sheets › Monitor Data Quality with Notion Rules, Sql Checks & Ai-powered Alerts

Monitor Data Quality with Notion Rules, Sql Checks & Ai-powered Alerts

ByYassin Zehar @yassinzehar on n8n.io

This workflow continuously validates data quality using rules stored in Notion, runs anomaly checks against your SQL database, generates AI-powered diagnostics, and alerts your team only when real issues occur.

Cron / scheduled trigger★★★★☆ complexityAI-powered21 nodesPostgresNotionOpenAIJiraSlackGmail
Data & Sheets Trigger: Cron / scheduled Nodes: 21 Complexity: ★★★★☆ AI nodes: yes Added:
Monitor Data Quality with Notion Rules, Sql Checks & Ai-powered Alerts — n8n workflow card showing Postgres, Notion, OpenAI integration

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

This workflow follows the Gmail → Notion 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": "RAVj412PdMc4kTPE",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Quality data check system",
  "tags": [
    {
      "id": "fqJGztMNmqQ1Q373",
      "name": "notion",
      "createdAt": "2025-11-26T16:21:14.436Z",
      "updatedAt": "2025-11-26T16:21:14.436Z"
    },
    {
      "id": "T75wN7b2Y1Q2X3nH",
      "name": "alert",
      "createdAt": "2025-11-20T18:06:09.140Z",
      "updatedAt": "2025-11-20T18:06:09.140Z"
    },
    {
      "id": "S94PaeZJiPKn5Ei9",
      "name": "gmail",
      "createdAt": "2025-08-14T09:57:18.678Z",
      "updatedAt": "2025-08-14T09:57:18.678Z"
    },
    {
      "id": "Unbn35P90TtJuAQC",
      "name": "email",
      "createdAt": "2025-08-14T09:57:13.394Z",
      "updatedAt": "2025-08-14T09:57:13.394Z"
    },
    {
      "id": "IUTR4oS3KHYPxOqH",
      "name": "Jira",
      "createdAt": "2025-11-14T09:45:17.977Z",
      "updatedAt": "2025-11-14T09:45:17.977Z"
    },
    {
      "id": "SenQnwINjVwewgLY",
      "name": "slack",
      "createdAt": "2025-11-20T18:05:28.955Z",
      "updatedAt": "2025-11-20T18:05:28.955Z"
    },
    {
      "id": "qCgJLisgQ1EsyJ62",
      "name": "sql",
      "createdAt": "2025-11-20T18:05:47.931Z",
      "updatedAt": "2025-11-20T18:05:47.931Z"
    }
  ],
  "nodes": [
    {
      "id": "cb4115ac-4f5f-4939-ba38-31439073c734",
      "name": "Product anomalies",
      "type": "n8n-nodes-base.postgres",
      "position": [
        784,
        -272
      ],
      "parameters": {
        "query": "SELECT *\nFROM {{ $json[\"Source\"] }}\nWHERE {{ $json[\"Rule\"] }};\n",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "4bb4dbab-6476-4bc8-9db6-2e9449d72e54",
      "name": "check orders",
      "type": "n8n-nodes-base.postgres",
      "position": [
        768,
        176
      ],
      "parameters": {
        "query": "SELECT \n  'orders' AS table_name,\n  id,\n  customer_id,\n  total_amount,\n  status,\n  created_at\nFROM orders\nWHERE \n    total_amount IS NULL\n    OR total_amount = 0\n    OR customer_id IS NULL\n    OR id IS NULL;\n",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "de7d4b56-045c-4d80-8405-c0935e19b6af",
      "name": "build summary",
      "type": "n8n-nodes-base.code",
      "position": [
        976,
        -48
      ],
      "parameters": {
        "jsCode": "const items = $input.all().map(i => i.json);\n\nconst anomalies = items;\nconst totalIssues = anomalies.length;\nconst totalRows = anomalies.length; \n\nconst score = totalIssues === 0\n  ? 100\n  : Math.max(0, 100 - Math.round((totalIssues / (totalRows || 1)) * 100));\n\nlet summary = `\ud83d\udcca Data Quality Report\\n\\n`;\nsummary += `Anomalies found: ${totalIssues}\\n`;\nsummary += `Quality score: ${score}/100\\n\\n`;\n\nanomalies.slice(0, 5).forEach((a, i) => {\n  summary += `${i + 1}. id=${a.id ?? \"N/A\"} | sku=${a.sku ?? \"N/A\"} | price=${a.price ?? \"N/A\"}\\n`;\n});\n\n\nreturn [\n  {\n    json: {\n      anomalies_found: totalIssues,\n      totalIssues,\n      totalRows,\n      qualityScore: score,\n      summary,          \n      summary_text: summary,\n      anomalies\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "5aa13ccf-c5d3-4a59-82b6-67e294274ebe",
      "name": "run metadata",
      "type": "n8n-nodes-base.set",
      "position": [
        1184,
        -64
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "aa5adb4a-13e2-495f-b215-548f850630e9",
              "name": "run_date",
              "type": "string",
              "value": "={{$now}}"
            },
            {
              "id": "b465d747-885f-4788-ad4b-08761eb7b933",
              "name": "run_id",
              "type": "number",
              "value": "={{$now}}-{{$randomNumber(1000,9999)}}"
            },
            {
              "id": "59aacd09-0863-4c35-ac1f-e3ca3b9f63f6",
              "name": "env",
              "type": "string",
              "value": "\"prod\""
            },
            {
              "id": "1af82ee3-2363-4017-aec4-afddb4a0b1c8",
              "name": "total_anomalies",
              "type": "number",
              "value": "={{$json[\"totalIssues\"]}}"
            },
            {
              "id": "b36da29e-d0b5-410a-8f7b-921e6cdb2a10",
              "name": "quality_score",
              "type": "number",
              "value": "={{$json[\"qualityScore\"]}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "649e1b53-f8c9-4ae1-9967-80979a12a075",
      "name": "Data quality run page",
      "type": "n8n-nodes-base.notion",
      "position": [
        2592,
        -48
      ],
      "parameters": {
        "title": "Data Quality Incidents",
        "pageId": {
          "__rl": true,
          "mode": "url",
          "value": "https://www.notion.so"
        },
        "blockUi": {
          "blockValues": [
            {
              "type": "heading_1",
              "textContent": "Data quality {{date}}"
            },
            {
              "textContent": "=Title = DQ Run - {{$json[\"run_date\"]}}\n\nRun Date = {{$json[\"run_date\"]}}\n\nEnv = {{$json[\"env\"]}}\n\nTotal anomalies = {{$json[\"total_anomalies\"]}}\n\nQuality score = {{$json[\"quality_score\"]}}"
            }
          ]
        },
        "options": {}
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "29bfbca8-5a53-4c42-8960-025de7b0b404",
      "name": "AI analysis and recommendation",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        1120,
        256
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {},
        "responses": {
          "values": [
            {
              "content": "=You are a DataOps expert.\n\nHere is a data quality report:\n\n{{ $json[\"summary\"] }}\n\nReturn JSON only:\n\n{\n \"Summary\": \"...\",\n \"Urgency\": \"High|Medium|Low\",\n \"Root_Causes\": [\"...\", \"...\", \"...\"],\n \"Recommended_Fix\": [\"...\", \"...\", \"...\"],\n \"Impact\": \"High|Medium|Low\"\n}\n"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "0aef1ab7-cabf-4e77-819e-20d796d27549",
      "name": "calculate trend",
      "type": "n8n-nodes-base.code",
      "position": [
        1408,
        -64
      ],
      "parameters": {
        "jsCode": "const current = $json.qualityScore ?? $json.quality_score ?? 100;\n$json.trend = 0;\nreturn [{ json: $json }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "f2f82d8c-7cac-4828-a721-3885a734ad7f",
      "name": "Autofix simulation",
      "type": "n8n-nodes-base.code",
      "position": [
        2192,
        -272
      ],
      "parameters": {
        "jsCode": "const rows = $json[\"anomalies\"] ?? [];\nrows.forEach(r => r.auto_fix = \"recommended\");\nreturn [{json:$json}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "6b7b101e-27fe-46dd-b9e7-e69be42777ed",
      "name": "split batch",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        320,
        0
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "176f8964-21c2-4164-8bc6-edb1cd15ab47",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -720,
        -448
      ],
      "parameters": {
        "width": 656,
        "height": 880,
        "content": "##  How it works\n\nThis workflow monitors data quality by running rule-based checks against your datasets and automatically alerting the team only when real anomalies are found \u2014 no noise, no manual review.\n\nEvery run begins by loading the Data Quality Rules from Notion, where each rule defines a dataset, a field, and a validation condition (e.g. price \u2264 0, missing ID, NULL amount). Rules are processed one-by-one and dynamically converted into live SQL queries, letting you scale checks without editing the workflow.\n\nQuery results are aggregated into a global summary, producing metrics such as total anomalies, severity, affected tables, and example rows. An AI node then generates a structured diagnostic: top issues, suspected root causes, impact assessment and recommended fixes.\n\n- If no anomaly is detected, the workflow ends quietly, clean runs remain silent and clutter-free.\n\n- If anomalies are detected, the workflow escalates. A Data Quality Run Page is created in Notion with full run metadata, trend score, and AI analysis. Depending on severity thresholds, the workflow can:\n\n- Send alerts to Slack or email\n\n- Create a Jira ticket for investigation\n\n- Tag anomalies with auto-fix suggestions\n\n- Log the incident for future audits\n\n- All runs are stored for long-term quality tracking, enabling dashboards, trend analysis, and continuous reliability improvement.\n\n## Setup steps\n\n- Create two Notion databases for quality runs and quality rules\n- Configure SQL database credentials \n- Add your OpenAI API credentials\n- Set up alert channels\n"
      },
      "typeVersion": 1
    },
    {
      "id": "9932aabc-8c8e-4a09-b47c-576ff173d297",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        -448
      ],
      "parameters": {
        "color": 7,
        "width": 1008,
        "height": 880,
        "content": "## 1) Data Quality Rules\n\nRuns configurable validation rules from Notion and executes SQL checks automatically."
      },
      "typeVersion": 1
    },
    {
      "id": "2c2b0c38-7b29-4c73-b3ae-abc30601f771",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        976,
        -448
      ],
      "parameters": {
        "color": 7,
        "width": 1056,
        "height": 880,
        "content": "## AI Summary & Scoring\n\nAggregates anomalies, generates a quality score, and provides root cause insights + recommended fixes."
      },
      "typeVersion": 1
    },
    {
      "id": "a056e103-e7a4-4a5b-b8b9-7da8eedc311a",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2048,
        -448
      ],
      "parameters": {
        "color": 7,
        "width": 1008,
        "height": 880,
        "content": "## 3) Incident Reporting & Alerts\n\nCreates Notion incident page, triggers Slack/Email/Jira alerts based on severity thresholds."
      },
      "typeVersion": 1
    },
    {
      "id": "5ef1e354-0eec-49ca-b7d0-dc700c4fb2d3",
      "name": "Daily trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        0,
        0
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 7
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "03cbc9dc-7bb4-4874-8434-65506099cacd",
      "name": "Get database data",
      "type": "n8n-nodes-base.notion",
      "position": [
        160,
        0
      ],
      "parameters": {
        "resource": "database",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "2b711ca2-096c-80d2-8b0c-c86fa3a0c76f",
          "cachedResultUrl": "https://www.notion.so",
          "cachedResultName": "Data quality rules"
        }
      },
      "credentials": {
        "notionApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "0132534e-b672-4171-aaa1-9bddeecb967f",
      "name": "Switch module",
      "type": "n8n-nodes-base.switch",
      "position": [
        560,
        16
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "aa22f58e-2fd8-4ae4-a722-fe17cdf60152",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "Source",
                    "rightValue": "products"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "1239bf99-a9bd-4405-b380-7e6306c9c259",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "Source",
                    "rightValue": "orders"
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.3
    },
    {
      "id": "b2fcd298-b15d-4848-98e7-d620525d4063",
      "name": "Issue condition",
      "type": "n8n-nodes-base.if",
      "position": [
        1632,
        -64
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "0b1fe073-4a47-4b3b-981b-380194743c47",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json[\"anomalies_found\"] }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "bf35311a-0c9f-4f28-9302-aa36bc10cc1b",
      "name": "Data condition",
      "type": "n8n-nodes-base.if",
      "position": [
        1824,
        -224
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "c5ea8aaf-544d-416b-82a7-e44ff97878dc",
              "operator": {
                "type": "number",
                "operation": "lt"
              },
              "leftValue": "={{ $json[\"quality_score\"] }}",
              "rightValue": 80
            },
            {
              "id": "16258b64-8979-4d4c-a384-617af6a22d4c",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json[\"total_anomalies\"] }}",
              "rightValue": 50
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "bd7ea0ff-72d8-4efa-af0e-9b1609761c39",
      "name": "Jira issue",
      "type": "n8n-nodes-base.jira",
      "position": [
        2432,
        -288
      ],
      "parameters": {
        "project": {
          "__rl": true,
          "mode": "list",
          "value": "10002",
          "cachedResultName": "test2"
        },
        "summary": "=Data Quality Incident \u2013 {{$json[\"run_date\"]}}",
        "issueType": {
          "__rl": true,
          "mode": "list",
          "value": "10013",
          "cachedResultName": "Bug"
        },
        "additionalFields": {
          "priority": {
            "__rl": true,
            "mode": "list",
            "value": "2",
            "cachedResultName": "High"
          },
          "description": "={{$json[\"summary\"]}}"
        }
      },
      "credentials": {
        "jiraSoftwareCloudApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "83fdb751-de5d-47dc-944e-8a981dfbb21a",
      "name": "Slack message alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        2784,
        -368
      ],
      "parameters": {
        "text": "=:rotating_light: *Data Quality Alert* ({{ $json[\"env\"] }}) \u2013 {{ $json[\"run_date\"] }}\n\n\u2022 Total anomalies : {{ $json[\"total_anomalies\"] }}\n\u2022 Quality score : {{ $json[\"quality_score\"] }}/100\n\nSumup :\n{{ $json[\"summary\"] }}\n\nplease check asap. :eyes:\n",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0A030UC0BW",
          "cachedResultName": "data"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "e665cffc-44f5-4483-91bc-8cbb4be8095a",
      "name": "Email reporting",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2800,
        224
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "=Hi Data Team,  please find below the data quality report :  <pre>{{ $json[\"summary_text\"] }}</pre>  an incident has been \u00e9created in Notion : - Link : \nHave a great day",
        "options": {},
        "subject": "=Data Quality Report \u2013 {{date}}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "61ca3db1-d2be-4869-8d98-1567c9fdd0e0",
  "connections": {
    "Jira issue": {
      "main": [
        [
          {
            "node": "Data quality run page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "split batch": {
      "main": [
        [],
        [
          {
            "node": "Switch module",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "check orders": {
      "main": [
        [
          {
            "node": "build summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "run metadata": {
      "main": [
        [
          {
            "node": "calculate trend",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily trigger": {
      "main": [
        [
          {
            "node": "Get database data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch module": {
      "main": [
        [
          {
            "node": "Product anomalies",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "check orders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "build summary": {
      "main": [
        [
          {
            "node": "AI analysis and recommendation",
            "type": "main",
            "index": 0
          },
          {
            "node": "run metadata",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Data condition": {
      "main": [
        [
          {
            "node": "Autofix simulation",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Data quality run page",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Issue condition": {
      "main": [
        [
          {
            "node": "Data condition",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "calculate trend": {
      "main": [
        [
          {
            "node": "Issue condition",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get database data": {
      "main": [
        [
          {
            "node": "split batch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Product anomalies": {
      "main": [
        [
          {
            "node": "build summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Autofix simulation": {
      "main": [
        [
          {
            "node": "Jira issue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack message alert": {
      "main": [
        []
      ]
    },
    "Data quality run page": {
      "main": [
        [
          {
            "node": "Email reporting",
            "type": "main",
            "index": 0
          },
          {
            "node": "Slack message alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI analysis and recommendation": {
      "main": [
        [
          {
            "node": "calculate trend",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

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

This workflow continuously validates data quality using rules stored in Notion, runs anomaly checks against your SQL database, generates AI-powered diagnostics, and alerts your team only when real issues occur.

Source: https://n8n.io/workflows/11256/ — 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

This workflow transforms raw SaaS metrics into a fully automated Product Health Monitoring & Incident Management system.

Postgres, OpenAI, Slack +2
Data & Sheets

Scheduled processes retrieve customer feedback from multiple channels. The system performs sentiment analysis to classify tone, then uses OpenAI models to extract themes, topics, and urgency indicator

HTTP Request, Lm Chat Azure Open Ai, Sentiment Analysis +5
Data & Sheets

This workflow is designed for Customer Success Managers, Growth Teams, and SaaS Business Owners who want to proactively reduce churn using AI. It automates the analysis of customer health and the deli

HTTP Request, Postgres, OpenAI +2
Data & Sheets

This workflow functions as an automated "Chief Wellness Officer," helping HR teams and managers prevent employee burnout before it happens. It aggregates data from communication channels and work tool

HTTP Request, Slack, OpenAI +2
Data & Sheets

This workflow automatically identifies users who started but did not complete the signup process. It runs on a fixed schedule, checks your database for inactive and incomplete users, and validates the

Postgres, Slack, @Itechnotion/N8N Nodes Inboxplus +1