This workflow corresponds to n8n.io template #6190 — we link there as the canonical source.
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 →
{
"id": "G9psPUm3yJXIKj9m",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "\ud83c\udf31 Check Data Freshness",
"tags": [],
"nodes": [
{
"id": "01241280-49c4-47d1-a09c-3277e5313d13",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-160,
432
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1.2
},
{
"id": "3c5924ab-1d15-4747-b18c-a047d1f1e26b",
"name": "Loop Over Items",
"type": "n8n-nodes-base.splitInBatches",
"position": [
304,
432
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "4fd6e105-9bc9-4494-964f-755d86940117",
"name": "Aggregate Stale Tables",
"type": "n8n-nodes-base.aggregate",
"position": [
1120,
272
],
"parameters": {
"options": {},
"fieldsToAggregate": {
"fieldToAggregate": [
{
"renameField": true,
"outputFieldName": "tables",
"fieldToAggregate": "table"
}
]
}
},
"typeVersion": 1
},
{
"id": "ee5378e3-3907-419b-8ca5-53e26abeb295",
"name": "Get most recent row from table",
"type": "n8n-nodes-base.postgres",
"position": [
528,
432
],
"parameters": {
"sort": {
"values": [
{
"column": "={{ $json.timestampColumn }}",
"direction": "DESC"
}
]
},
"limit": 1,
"table": {
"__rl": true,
"mode": "name",
"value": "={{ $json.tableName }}"
},
"schema": {
"__rl": true,
"mode": "list",
"value": "public"
},
"options": {},
"operation": "select"
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.6
},
{
"id": "41b21d6f-0134-424e-87af-05cd38a8997b",
"name": "Calculate lag",
"type": "n8n-nodes-base.dateTime",
"position": [
704,
432
],
"parameters": {
"endDate": "={{ $now }}",
"options": {},
"operation": "getTimeBetweenDates",
"startDate": "={{ $json[$('Produce tables + date columns').item.json.timestampColumn] }}"
},
"typeVersion": 2
},
{
"id": "3b09f150-585a-41aa-9343-d68ca08c94c2",
"name": "Add back table name",
"type": "n8n-nodes-base.set",
"position": [
864,
432
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "8f72670f-9e0e-425b-a5a6-0986d2e475d1",
"name": "daysOld",
"type": "number",
"value": "={{ $json.timeDifference.days }}"
},
{
"id": "1d5bd3ec-a1b5-4d40-94ca-15d22696d5f0",
"name": "table",
"type": "string",
"value": "={{ $('Produce tables + date columns').item.json.tableName }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "e8749421-ced2-4951-9b28-d003513aefd7",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
64,
208
],
"parameters": {
"width": 976,
"height": 432,
"content": "## Find tables with stale data"
},
"typeVersion": 1
},
{
"id": "b6c620c4-16c0-402b-b18e-047ed9a7da82",
"name": "Remove fresh tables",
"type": "n8n-nodes-base.filter",
"position": [
528,
272
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "dc7e2a08-be0b-4226-b2f8-cd7609b1d61e",
"operator": {
"type": "number",
"operation": "gte"
},
"leftValue": "={{ $json.daysOld }}",
"rightValue": 3
}
]
}
},
"typeVersion": 2.2
},
{
"id": "99b1aa9a-ab2c-437a-959a-bffc86d5e153",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-672,
-528
],
"parameters": {
"width": 656,
"height": 928,
"content": "# Monitor Postgres Data Freshness and Email Alert If Stale\nThis template monitors a set of tables inside a Postgres database to ensure they're getting updated.\n\nIf the table hasn't been updated in 3 days (configurable), an email alert is sent containing the tables that are stale.\n\n## Requirements\nYou must have a Postgres database containing one or more tables that you'd like to monitor.\n\nEach table to monitor must have a date or timestamp column that tracks when data was pushed.\n\nFor example, this might be:\n\n- A `timestamp` column if your table holds event/timeseries data\n- A `last_updated` column if your rows are expected to be modified\n\n## Usage\n1. Use this template\n1. Add your Postgres and email credentials\n1. Adjust the `Produce tables + date columns` node to produce pairs of `[table, date_column]` that should be monitored for freshness\n - \ud83d\udc81\u200d\u2642\ufe0f Note that a timestamp column also works\n1. (Optional) Adjust the `Remove fresh tables` node for your desired staleness window (default is 3 days, but you can adjust as you please)\n1. (Optional) Customize the `Send alerts` node to call whichever alerting workflow you please (I recommend [my alerting workflow](https://creators.n8n.io/workflows/6189) for easiest plug-and-play)\n\n## How it works\nThis template works by:\n\n1. Pulling the most recent row for each table\n1. Calculating how out-of-date each table is, in days\n1. Dropping fresh tables that have been updated within the past 3 days\n1. Sending an email alert with the stale tables that haven't been updated within the past 3 days\n"
},
"typeVersion": 1
},
{
"id": "9f2c4f7e-afee-4293-acc9-a3b854814986",
"name": "Produce tables + date columns",
"type": "n8n-nodes-base.code",
"position": [
112,
432
],
"parameters": {
"jsCode": "const VALUE_TUPLES = [\n [\"sleep_summary\",\"sleep_date\"],\n [\"mac_screentime_sessions\", \"ts\"],\n]\n\nlet result = []\nfor (const [tableName, timestampCol] of VALUE_TUPLES) {\n result.push({\n \"tableName\": tableName,\n \"timestampColumn\": timestampCol,\n })\n}\nreturn result;"
},
"typeVersion": 2
},
{
"id": "11b1618a-eb84-4f09-8678-51914758e3c5",
"name": "Send alerts",
"type": "n8n-nodes-base.executeWorkflow",
"position": [
1328,
272
],
"parameters": {
"options": {},
"workflowId": {
"__rl": true,
"mode": "list",
"value": "17yjHH5i669dVRGk",
"cachedResultName": "\u2757 Send Alert"
},
"workflowInputs": {
"value": {
"body": "=The following quantified life tables are stale (>=3 days old):\n{{ $json.tables.join(\"\\n\") }}",
"subject": "Stale Quantified Life Data"
},
"schema": [
{
"id": "subject",
"type": "string",
"display": true,
"required": false,
"displayName": "subject",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "body",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "body",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": true
}
},
"typeVersion": 1.2
},
{
"id": "ffa03d08-8596-42f3-82cf-0741373832c3",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1344,
-32
],
"parameters": {
"color": 3,
"width": 262,
"height": 336,
"content": "# (Optional)\n# Customize the alerting workflow\nI recommend [my alerting workflow](https://creators.n8n.io/workflows/6189)\n# \ud83d\udd3d\n"
},
"typeVersion": 1
},
{
"id": "08108247-6969-4544-90d1-ceaaa5091a9d",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
544,
-16
],
"parameters": {
"color": 3,
"width": 230,
"height": 304,
"content": "# (Optional)\n# Customize the stale threshold\n# \ud83d\udd3d\n"
},
"typeVersion": 1
}
],
"active": true,
"settings": {
"callerPolicy": "workflowsFromSameOwner",
"errorWorkflow": "94eLbjCAIMla9lSa",
"executionOrder": "v1"
},
"versionId": "55232ec1-8d2f-4639-bf66-e86c0b01f9fa",
"connections": {
"Calculate lag": {
"main": [
[
{
"node": "Add back table name",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[
{
"node": "Remove fresh tables",
"type": "main",
"index": 0
}
],
[
{
"node": "Get most recent row from table",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Produce tables + date columns",
"type": "main",
"index": 0
}
]
]
},
"Add back table name": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Remove fresh tables": {
"main": [
[
{
"node": "Aggregate Stale Tables",
"type": "main",
"index": 0
}
]
]
},
"Aggregate Stale Tables": {
"main": [
[
{
"node": "Send alerts",
"type": "main",
"index": 0
}
]
]
},
"Produce tables + date columns": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Get most recent row from table": {
"main": [
[
{
"node": "Calculate lag",
"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.
postgres
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This template monitors a set of tables inside a Postgres database to ensure they're getting updated.
Source: https://n8n.io/workflows/6190/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Disparador 1.8. Uses itemLists, postgres, emailSend, httpRequest. Scheduled trigger; 85 nodes.
공유회_알림톡_크론. Uses postgres, httpRequest, n8n-nodes-solapi. Scheduled trigger; 39 nodes.
QuepasaAutomatic. Uses postgres, postgresTrigger, httpRequest. Scheduled trigger; 39 nodes.
QuepasaAutomatic. Uses postgres, postgresTrigger, httpRequest. Scheduled trigger; 39 nodes.
QuepasaAutomatic. Uses postgres, postgresTrigger, httpRequest. Scheduled trigger; 39 nodes.