AutomationFlowsEmail & Gmail › Host Your Own Uptime Monitoring with Scheduled Triggers

Host Your Own Uptime Monitoring with Scheduled Triggers

ByJimleuk @jimleuk on n8n.io

This n8n workflow demonstrates how to build a simple uptime monitoring service using scheduled triggers.

Cron / scheduled trigger★★★★☆ complexity15 nodesGoogle SheetsSlackGmailHTTP Request
Email & Gmail Trigger: Cron / scheduled Nodes: 15 Complexity: ★★★★☆ Added:

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

This workflow follows the Gmail → Google Sheets 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
{
  "nodes": [
    {
      "id": "acb0acd0-9bb6-4491-a1ca-4aa9a7820bbc",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1440,
        420
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 6
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "c6bb51c4-aec4-4a6d-ade2-1080bbbb6fb3",
      "name": "Calculate Status",
      "type": "n8n-nodes-base.set",
      "position": [
        2367,
        460
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "b0cbcff5-bfcf-46a5-a386-65c4dd56c42f",
              "name": "date",
              "type": "string",
              "value": "={{ $json.headers.date }}"
            },
            {
              "id": "8c4155e4-bcc6-41dd-9582-346a57a7b997",
              "name": "Property",
              "type": "string",
              "value": "={{ $json.Property }}"
            },
            {
              "id": "f0320678-d352-486f-a633-9980c4fc73b2",
              "name": "UP_FROM_UP",
              "type": "boolean",
              "value": "={{ $json.statusCode < 400 && $json.Status === 'UP' }}"
            },
            {
              "id": "61783eb6-a683-44c9-aa0c-5fc5247da9fa",
              "name": "DOWN_FROM_DOWN",
              "type": "boolean",
              "value": "={{ $json.statusCode >= 400 && $json.Status === 'DOWN' }}"
            },
            {
              "id": "1052a69e-4456-445d-bdd9-2765b334cf64",
              "name": "UP_FROM_DOWN",
              "type": "boolean",
              "value": "={{ $json.statusCode < 400 && $json.Status === 'DOWN' }}"
            },
            {
              "id": "9af72278-5b29-406a-b4c5-f47f3d805063",
              "name": "DOWN_FROM_UP",
              "type": "boolean",
              "value": "={{ $json.statusCode >= 400 && $json.Status === 'UP' }}"
            }
          ]
        }
      },
      "typeVersion": 3.3
    },
    {
      "id": "50307dca-fa88-4a19-91a4-456866e529d4",
      "name": "Get Sites",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1700,
        420
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1t2RT3lxyxXj3X1y6klWvyhEJEazpkT3Hpi2ttEJRVT4/edit#gid=0",
          "cachedResultName": "dashboard"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1t2RT3lxyxXj3X1y6klWvyhEJEazpkT3Hpi2ttEJRVT4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1t2RT3lxyxXj3X1y6klWvyhEJEazpkT3Hpi2ttEJRVT4/edit?usp=drivesdk",
          "cachedResultName": "n8n uptime"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "4b0cb0cc-282b-4be9-a4ca-0c4eb10d896e",
      "name": "Send Chat Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        3100,
        340
      ],
      "parameters": {
        "text": "=From: n8n uptime\nDate: {{ $('Calculate Status').item.json[\"date\"] }}\n\n{{ $('Calculate Status').item.json.Property }} is {{ $('Calculate Status').item.json[\"DOWN_FROM_UP\"] ? 'DOWN' : 'UP' }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C06RS1WPUQ6",
          "cachedResultName": "general"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "ab303995-bd82-4aef-8fe1-ce808c4dbd33",
      "name": "Send Email Alert",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2940,
        340
      ],
      "parameters": {
        "sendTo": "no-reply@example.com",
        "message": "=From: n8n uptime\nDate: {{ $('Calculate Status').item.json[\"date\"] }}\n\n{{ $('Calculate Status').item.json.Property }} is {{ $('Calculate Status').item.json[\"DOWN_FROM_UP\"] ? 'DOWN' : 'UP' }}",
        "options": {
          "senderName": "n8n uptime",
          "appendAttribution": false
        },
        "subject": "=n8n uptime: {{ $('Calculate Status').item.json.Property }} is {{ $('Calculate Status').item.json[\"DOWN_FROM_UP\"] ? 'DOWN' : 'UP' }}",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "63343e68-be07-4d89-8363-140299dcf0b6",
      "name": "Log Uptime Event",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2940,
        520
      ],
      "parameters": {
        "columns": {
          "value": {
            "date": "={{ $json.date }}",
            "period": "={{ new Date($json.date).format(\"yyyy-MM\") }}"
          },
          "schema": [
            {
              "id": "period",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "period",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Property",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Property",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "UP_FROM_UP",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "UP_FROM_UP",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DOWN_FROM_DOWN",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "DOWN_FROM_DOWN",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "UP_FROM_DOWN",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "UP_FROM_DOWN",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DOWN_FROM_UP",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "DOWN_FROM_UP",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "={{ $('Calculate Status').item.json.Property }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1t2RT3lxyxXj3X1y6klWvyhEJEazpkT3Hpi2ttEJRVT4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1t2RT3lxyxXj3X1y6klWvyhEJEazpkT3Hpi2ttEJRVT4/edit?usp=drivesdk",
          "cachedResultName": "n8n uptime"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "fe97a18b-902c-4fab-bf73-69b5b9e41a11",
      "name": "Update Site Status",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3100,
        520
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "={{ $json[\"DOWN_FROM_UP\"] || $json[\"DOWN_FROM_DOWN\"] ? 'DOWN' : 'UP' }}",
            "Property": "={{ $json.Property }}"
          },
          "schema": [
            {
              "id": "Property",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Property",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Property"
          ]
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1t2RT3lxyxXj3X1y6klWvyhEJEazpkT3Hpi2ttEJRVT4/edit#gid=0",
          "cachedResultName": "dashboard"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1t2RT3lxyxXj3X1y6klWvyhEJEazpkT3Hpi2ttEJRVT4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1t2RT3lxyxXj3X1y6klWvyhEJEazpkT3Hpi2ttEJRVT4/edit?usp=drivesdk",
          "cachedResultName": "n8n uptime"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "b37537d1-eedf-446e-a5ed-2ef7388fd7bc",
      "name": "Perform Site Test",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2207,
        460
      ],
      "parameters": {
        "url": "={{ $json.Property }}",
        "options": {
          "response": {
            "response": {
              "neverError": true,
              "fullResponse": true
            }
          }
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {}
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "22efcca8-81a8-4128-a03f-efd394e41977",
      "name": "For Each Site...",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        2007,
        460
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "b74d0b2c-8b08-42fe-a78f-103d4ea3b60f",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1375.3365733151754,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 533.3167991131336,
        "height": 451.46281790887826,
        "content": "## 1. Setting a Schedule\n[Read more about Scheduling Workflows](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.scheduletrigger/)\n\nSince we expect downtime to be a rare occurance, our monitor should only check infrequently during the day. We'll use a schedule trigger for this purpose.\n\nOnce the schdule activates, we'll pull a list of sites to check from our google sheet."
      },
      "typeVersion": 1
    },
    {
      "id": "6c570ff2-aa08-4458-b2da-7632d516c4e3",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1940,
        247.83581204342858
      ],
      "parameters": {
        "color": 7,
        "width": 596.6620781418152,
        "height": 464.2968162619932,
        "content": "## 2. Perform Site Checks\n[Read more about using HTTP requests](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.httprequest/)\n\nn8n makes it easy to communicate with external websites by offering a powerful HTTP request node which can handle GET and POST requests as well as pagination.\n\nHere, we're only interested in the status code of our requests."
      },
      "typeVersion": 1
    },
    {
      "id": "d1f67650-1409-43b1-b197-0e5a821d8b6f",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2580,
        117.20168629145996
      ],
      "parameters": {
        "color": 7,
        "width": 720.3351531809235,
        "height": 600.2604061412927,
        "content": "## 3. Sending Alerts and Logging Results\n[Read more about using Switch for powerful control flow](https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.switch)\n\nThe switch node is powerful control flow tool that makes your workflows smart. Here, we're able to use Switch to trigger alert notifications whenever we have DOWN status or whenever we get a status change.\n\nWe store the event in our Sites Google Sheet and update the site's status which will be used to calculate our state on the next scheduled run."
      },
      "typeVersion": 1
    },
    {
      "id": "244291de-7ce1-48c9-9d7a-c04fc7d069ab",
      "name": "Status Router",
      "type": "n8n-nodes-base.switch",
      "position": [
        2640,
        520
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "UP_FROM_UP",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.UP_FROM_UP }}",
                    "rightValue": 200
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "UP_FROM_DOWN",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "f50ae8d6-4359-4163-aedb-fddf100ad676",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.UP_FROM_DOWN }}",
                    "rightValue": 200
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "DOWN_FROM_DOWN",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "417e93d8-08b7-468d-a3bb-f0d395b3026a",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.DOWN_FROM_DOWN }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "DOWN_FROM_UP",
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "7191e7cb-f2e1-4288-aa68-21f6efefafc5",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.DOWN_FROM_UP }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "a2a683fa-1fa5-4595-856a-de4f717eadf0",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1063.07390978683,
        160
      ],
      "parameters": {
        "width": 276.590892958905,
        "height": 299.942498076894,
        "content": "## Try It Out!\n### Thie workflow showcases how you can build a simple website monitoring service using Scheduled Triggers and the HTTP Requests node. \n\n### Need Help?\nJoin the [Discord](https://discord.com/invite/XPKeKXeB7d) or ask in the [Forum](https://community.n8n.io/)!\n\nHappy Hacking!"
      },
      "typeVersion": 1
    },
    {
      "id": "704ce21f-6b96-4dc5-a27f-fca4b326efd1",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1620,
        380
      ],
      "parameters": {
        "width": 262.6069985025353,
        "height": 379.4991553144906,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n### \ud83d\udea8Google Sheet Required!\nYou'll need the following columns:\n* **Property** - the website address to monitor\n* **Status** - either one of \"UP\" or \"DOWN\""
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Get Sites": {
      "main": [
        [
          {
            "node": "For Each Site...",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Status Router": {
      "main": [
        [
          {
            "node": "Log Uptime Event",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Email Alert",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log Uptime Event",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log Uptime Event",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send Email Alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Email Alert",
            "type": "main",
            "index": 0
          },
          {
            "node": "Log Uptime Event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Status": {
      "main": [
        [
          {
            "node": "Status Router",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "For Each Site...": {
      "main": [
        null,
        [
          {
            "node": "Perform Site Test",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log Uptime Event": {
      "main": [
        [
          {
            "node": "Update Site Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get Sites",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Email Alert": {
      "main": [
        [
          {
            "node": "Send Chat Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Perform Site Test": {
      "main": [
        [
          {
            "node": "Calculate Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Site Status": {
      "main": [
        [
          {
            "node": "For Each Site...",
            "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 n8n workflow demonstrates how to build a simple uptime monitoring service using scheduled triggers.

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

More Email & Gmail workflows → · Browse all categories →

Related workflows

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

Email & Gmail

E-commerce store owners, product managers, marketplace sellers, and pricing analysts who want to automatically track competitor pricing and get actionable alerts when their products are overpriced or

Google Sheets, HTTP Request, Slack +1
Email & Gmail

This template is ideal for developers, agencies, hosting providers, and website owners who need real-time alerts when a website goes down. It helps teams react quickly to downtime by sending multi-cha

Slack, HTTP Request, Gmail +1
Email & Gmail

Schedule Slack. Uses scheduleTrigger, googleSheets, slack, gmail. Scheduled trigger; 15 nodes.

Google Sheets, Slack, Gmail +1
Email & Gmail

Restaurant owners, retail store managers, and small business owners who want to stay on top of customer feedback without manually checking Google reviews multiple times a day. Perfect for businesses t

HTTP Request, Chain Llm, Google Sheets +3
Email & Gmail

YOUR_ID 4. Uses gmail, googleDrive, googleSheets, httpRequest. Scheduled trigger; 53 nodes.

Gmail, Google Drive, Google Sheets +1