Skip to main content
Lifetime license included with every purchase
n8n workflowsssl monitoringdevops automationcert expiry

n8n SSL Certificate Monitoring That Escalates Before You Expire

Build n8n SSL certificate monitoring that escalates at 30, 14, and 3 days, skips the daily nag, confirms renewal, and tells a dead cert from a broken handshake.

Nn8n Marketplace Team·September 12, 2026·Updated September 12, 2026·7 min read

A 30-Day SSL Alert Is the One Nobody Acts On

The point of n8n SSL certificate monitoring isn't to know a cert expires. It's to make sure someone renews it before it does. Those are different jobs, and most of the workflows that rank for this only do the first one. They ping once at 30 days, the message scrolls past, and the cert lapses anyway on a Saturday.

Look at the popular templates. The SSL/TLS expiry monitor with Slack alert runs a clean five-node flow (Cron, a Code node holding the domain list, HTTP Request, an IF, a Slack message) with a single 30-day threshold baked into new Date(Date.now() + 30 * 24 * 60 * 60 * 1000). The multi-channel version with Google Sheets logs to a sheet but still fires on one window. The no-paid-APIs notifier is bare. None of them escalate, none de-duplicate, and none confirm the renewal actually happened.

n8n is a good fit here because you control the escalation logic. You decide how loud each window gets, who it reaches, and when to stop nagging.

What an SSL Monitor Worth Keeping Actually Does

A monitor people trust does more than read an expiry date:

  • Tiered escalation: a quiet notice at 30 days, a real alert at 14, an on-call page at 3
  • De-duplication: one alert per tier per domain, not the same warning every morning
  • Renewal confirmation: a "resolved" message when the expiry date jumps forward
  • Handshake errors: treat a failed TLS connection as a live incident, not a future date
  • Multi-domain: one workflow over a maintained list, not a workflow per cert
  • History: every check logged so you can prove what was healthy when

The SSL Monitoring Pipeline

Schedule Trigger (daily, 8am)
  → Code (load domain list)
  → HTTP Request (SSL check per domain, continueOnFail: true)
  → IF (connection succeeded?)
      → yes:
          → Code (daysLeft = (expiry - now) / 86400000)
          → Switch (daysLeft <= 3 / <= 14 / <= 30)
          → IF (tier changed since last run?)  ← reads state from Sheets
              → Slack / on-call (tier-appropriate alert)
          → Google Sheets (upsert domain, daysLeft, tier, checkedAt)
      → no:
          → Slack #incidents (live TLS handshake error — not an expiry)
          → Google Sheets (log error state)

1. Run it daily, not hourly

Certs expire on a date, not a clock. A daily Schedule Trigger at a fixed morning hour catches every window with one check per domain per day. Hourly checks add 24x the load and tell you nothing new. Pick a time when someone's around to see the 3-day escalation, not 3am.

2. Compute days left, then branch into tiers

The HTTP Request node hits an SSL checker (SSL-Checker.io and similar return the valid_till date) with continue-on-fail set, so a dead host doesn't halt the run.

// Code node after the SSL check — tier the warning
const expiry = new Date($json.valid_till);
const daysLeft = Math.floor((expiry - Date.now()) / 86400000);
let tier = "ok";
if (daysLeft <= 3) tier = "critical";
else if (daysLeft <= 14) tier = "warning";
else if (daysLeft <= 30) tier = "notice";
return [{ json: { domain: $json.host, daysLeft, tier } }];

A Switch node then routes each tier to its own destination. The 30-day notice goes to a low-traffic channel. The 3-day critical pages on-call.

3. De-duplicate so you stop nagging

Here's the part the ranking templates skip, and it's the whole game. Without memory, the monitor re-fires the same warning every single morning until the cert renews. Store the last tier sent per domain in a Google Sheets row. Only alert when the tier changes (ok→notice, notice→warning, warning→critical). A cert sitting at 12 days out sends exactly one 14-day alert, not fourteen.

The state row is the difference between trusted and muted

A monitor with no memory of what it already sent is a monitor that gets muted in a week. The fix is one Google Sheets row per domain holding the last alert tier. Read it at the start of the run, compare, write it back at the end. The channel sees a clean escalation (notice, then warning, then critical) instead of the same line forty times. This single pattern is why hand-rolled SSL monitors fail and pre-wired ones don't.

4. Separate a dead cert from a dead handshake

A valid cert expiring next week and a TLS handshake failing right now are not the same alert. The first is a calendar item. The second is an outage. Branch on whether the connection even succeeded: a clean check with a near date goes to the expiry track, a connection failure (wrong cert served, protocol mismatch, host down) goes straight to the incident channel labeled as a live TLS error. Mixing them buries today's outage under next week's reminder.

5. Confirm the renewal

When the expiry date on a domain jumps forward (someone renewed), fire a short "resolved: cert renewed, now valid through X" message and reset the tier state to ok. This closes the loop. The team sees the cert was at risk and is now fine, instead of wondering whether the 3-day page was ever handled.

Implementation Patterns

Pattern 1 — Escalate by audience, not just by message. A 30-day notice and a 3-day page shouldn't land in the same place. Route quiet warnings to a #ops channel and critical ones to on-call. The AI Ops Watchtower template ships this tiered routing with the per-domain state row already wired, so escalation and de-duplication come for free.

Switch (tier) → notice → #ops ; warning → #ops + email ; critical → on-call

Pattern 2 — Snapshot the issuer too. A cert that quietly changes issuer can signal a misconfigured renewal or worse. Log the issuer alongside the expiry date, and flag a change. It's a cheap extra assertion on data you already pulled.

Pattern 3 — One list, many domains. Keep the monitored domains in a Sheet, not a Code node. Adding a site is a row edit. The check loop never changes.

n8n Nodes You'll Use Most

NodePurpose
Schedule TriggerRun the cert check once a day
HTTP RequestQuery the SSL checker, capture expiry and validity
CodeCompute days left, manage per-domain tier state
SwitchRoute 30 / 14 / 3-day windows to the right destination
IFDetect tier change and renewal, branch handshake errors
Google SheetsStore the state row and the check history
SlackSend tier-appropriate alerts and the renewed notice

Getting Started

  1. Add a Schedule Trigger set to once daily at a staffed hour.
  2. Load the domain list from a Google Sheets read.
  3. Add an HTTP Request to your SSL checker with continue-on-fail.
  4. Compute days left and the tier in a Code node.
  5. Wire the Switch to tiered destinations, and the tier-change IF off the state row.
  6. Branch handshake failures straight to the incident channel.
  7. Log every result, then start from a template rather than rebuilding the de-dupe state by hand.
Browse monitoring templates

For the broader on-call picture, automating DevOps workflows with n8n connects cert monitoring to incident response, and n8n uptime monitoring with Slack alerts uses the same de-duplication discipline for page-level outages. If your certs and your domains expire on different calendars, pair this with AI Ops Watchtower for the endpoint side.

Skip the build

The AI Ops Watchtower ships SSL checks with the tiered escalation, the per-domain state row that kills the daily nag, the handshake-vs-expiry branch, and the renewed-confirmation notice, all pre-wired to Slack and a Google Sheets history. It's part of The Complete n8n Templates Bundle, a one-time lifetime license to every template and the ones added later, which pays off the moment you monitor more than one cert.

Get the AI Ops Watchtower
FAQ

Common questions

How early should an SSL expiry alert fire?
Not once, but in tiers. A single 30-day ping gets ignored because 30 days feels like forever, then nobody remembers it. Fire a low-priority notice at 30 days, a real one at 14, and an escalation to the on-call channel at 3 days. The closer the expiry, the louder the alert and the more people it reaches. One alert at one threshold is the pattern that lets certs lapse anyway.
Why does my SSL monitor alert every single day until the cert is renewed?
Because it re-checks the expiry date and re-fires every run, with no memory of what it already sent. Store a per-domain state (last alert tier sent) in a Google Sheets cell. Only alert when the tier changes, so a cert sitting at 12 days out sends one 14-day alert, not a fresh one every morning for two weeks. That daily nag is why teams mute the channel.
Can n8n tell an expiring certificate from a broken TLS handshake?
It should, because they need different responses. An expiring cert is a calendar problem you fix next week. A handshake that fails today (wrong cert, protocol mismatch, host unreachable) is an outage right now. Branch on the check result: a valid cert with a near date goes to the expiry track, a failed connection goes straight to the incident channel labeled as a live TLS error, not a future expiry.
Stop reading. Start running.

Get the workflow templates this guide is built on

Import-ready n8n JSON, step-by-step setup, and tested end-to-end. One-time payment, own it forever.

Free — $40 value

Get 3 tested n8n templates, free

The full customer package for three real catalog templates — workflow JSON, step-by-step setup guide, credential checklist. Built through the same live-instance release process as everything we sell. Plus new templates and automation guides in your inbox. No spam, unsubscribe anytime.

  • 01Smart To-Do List ManagerPre-built n8n workflow template that automates productivity with OpenAI. Live in about 10 minutes.$14
  • 02Email Follow-Up AutomatorPre-built n8n workflow template that automates crm with OpenAI. Live in about 15 minutes.$12
  • 03Market Trend AnalyzerPre-built n8n workflow template that automates data processing with OpenAI. Live in about 10 minutes.$14