Skip to main content
Lifetime license included with every purchase
n8n workflowsSLA alertssupport opsresponse time

How to Build n8n SLA Breach Alerts That Fire Once

Build n8n SLA breach alerts with business-hours-aware clocks, 75/90 percent warnings, and an alert-state flag so each threshold fires once, no helpdesk needed.

Nn8n Marketplace Team·August 21, 2026·Updated August 21, 2026·8 min read

An SLA is a promise with a clock attached, and the clock runs whether anyone's watching it or not. A four-hour response target means nothing if the first time anyone checks is when the customer emails to ask why it's been six. n8n SLA breach alerts put a warning in front of the deadline instead of an apology after it, and they do it without spamming the channel every time the cron fires.

The strongest competitor here gets the warning right and the dedupe wrong. The n8n library's proactive SLA monitoring template computes percent-elapsed and alerts at 75% and 90%, which is the correct shape. But it hard-requires Zendesk and re-fires the same alert on every run. Guides like OneClick's SLA monitoring post and Equanax's RevOps SLA piece describe the alerting but skip the two things that make it usable: a business-hours-aware clock and an alert-state flag.

Those two fixes are the post. And none of it needs a help desk.

Why a breached SLA is usually a silent failure

SLAs don't break loudly. A ticket ages past its target with no error, no exception, no red light. The workflow that was supposed to catch it either never existed or fires so often that the team muted it months ago. Both failure modes end the same way: a customer notices before you do.

Getting this right means two clocks done correctly. The first is the elapsed-time clock, which has to know your support hours or it'll report weekend false alarms. The second is the alert clock, which has to remember what it already said or it'll repeat itself into irrelevance. Tutorials nail the threshold percentages and miss both of these.

What you can automate in SLA monitoring

  • A recurring read of every open ticket and its SLA target
  • Elapsed-time math that subtracts non-business hours and holidays
  • Percent-consumed calculation against each ticket's target duration
  • A 75% warning to the assigned agent before the deadline
  • A 90% breach alert that escalates and bumps the ticket's priority
  • An alert-state flag so each threshold announces exactly once
  • A Google Sheets log of every SLA event for the compliance report

Arithmetic and rules, again. The only judgment call is choosing thresholds, and 75/90 is a sane default to start from.

The SLA alert pipeline

Schedule trigger (every 10–15 min)
  → Read open tickets (Sheets / help desk)
  → Code (business-hours elapsed → % consumed)
  → Compare % to alert_state (already warned at this level?)
  → New threshold crossed → alert + update alert_state
  → Sheets log

The alert_state field is the load-bearing piece. It's what makes a workflow that runs 96 times a day send two alerts per ticket instead of ninety.

1. Read the open tickets

A Schedule trigger every 10–15 minutes pulls open tickets. The required fields are small: ticket_id, created_at, sla_target_minutes, priority, and alert_state. On Zendesk that's an API search; on a lean stack it's a Google Sheets read where each open ticket is a row. Either way, the SLA math operates on those five fields and nothing else.

Keep the read scoped to open or pending tickets. Pulling closed tickets through the clock wastes calls and risks alerting on something already resolved.

2. Compute elapsed time the way the team works

A naive clock treats 4 hours as 240 wall-clock minutes. A useful clock knows your team doesn't work nights and weekends. The Code node computes business-hours-elapsed:

const open = new Date($json.created_at);
const now = new Date();
// businessMinutes(): counts only Mon-Fri 09:00-18:00 between two dates
const elapsed = businessMinutes(open, now);
const pct = Math.round((elapsed / $json.sla_target_minutes) * 100);
return [{ json: { ...$json, pct } }];

A ticket opened at 5:55pm Friday should read as 5 minutes elapsed on Monday at 9:05am, not as three days breached. Skip the business-hours adjustment and Monday morning is a wall of false breaches that nobody trusts. The first time that happens, the channel gets muted, and the alerts may as well not exist.

3. Compare against what you already said

Here's the dedupe. Each ticket carries an alert_state — the highest threshold already announced (none, warned, breached). The workflow only alerts when the current percentage crosses a new line:

let next = $json.alert_state;
if ($json.pct >= 90 && $json.alert_state !== "breached") next = "breached";
else if ($json.pct >= 75 && $json.alert_state === "none") next = "warned";
const shouldAlert = next !== $json.alert_state;
return [{ json: { ...$json, next, shouldAlert } }];

A ticket sitting at 82% has already been warned, so the next run that still reads 82% does nothing. When it crosses 90%, shouldAlert flips true once, the alert sends, and alert_state updates to breached. After that it's quiet again. One warning, one breach, per ticket. That's the entire trick the ranking template misses.

4. Alert and write the state back

For tickets where shouldAlert is true, send the alert and immediately write the new alert_state back to the source. Order matters: update the state in the same run, before the next cron tick can re-read the old value. A 75% warning pings the assigned agent. A 90% breach pings the support lead, bumps priority to High, and appends a compliance row.

The alert-state flag is non-negotiable

A breached ticket stays breached until someone closes it, so a workflow that alerts on "currently breached" alerts forever — every 10 minutes, for hours, on the same ticket. Within a day the team filters the channel and the SLA system is decorative. The cure is one field that remembers the last threshold announced. Persist it on the ticket, check it before alerting, update it after. An in-memory counter resets on restart and you're back to the firehose.

Implementation patterns worth copying

Pattern A — per-priority SLA targets. A P1 might owe a 1-hour first response, a P3 an 8-hour one. Store sla_target_minutes per ticket from a small priority lookup at creation, so the same percent-consumed math serves every tier without a separate workflow per priority.

Pattern B — the at-risk digest. Real-time alerts catch the ticket about to breach. A once-daily Schedule trigger that lists everything currently between 50% and 90% catches the slow burners early, while there's still time to act before they hit the warning line at all.

Thresholds, set honestly

75% and 90% are reasonable defaults, not law. Set the warning earlier (60%) for tight P1 windows where an hour is the whole budget, and later for relaxed P3s where a warning at 75% of eight hours still leaves two hours of runway. The point of the warning is to leave enough time to act. A warning that fires with five minutes left is just a pre-breach notification.

n8n nodes you'll use most

NodePurpose
Schedule TriggerRe-check open tickets every 10–15 minutes
HTTP / Zendesk / Google SheetsRead the open-ticket list and its SLA fields
CodeBusiness-hours elapsed and percent-consumed math
If / SwitchBranch on whether a new threshold was crossed
Set / Sheets UpdateWrite the new alert_state back to the ticket
SlackSend the 75% warning and 90% breach alerts
Google Sheets (append)Log every SLA event for the compliance report

Getting started

  1. Give every open ticket five fields: created_at, sla_target_minutes, priority, alert_state, ticket_id.
  2. Build a Schedule trigger that reads open tickets every 10 minutes.
  3. Write the business-hours elapsed function and the percent-consumed calculation.
  4. Add the alert-state comparison so only newly crossed thresholds alert.
  5. Send the alert, then update alert_state in the same run before anything else.
  6. Test with a ticket near each threshold and confirm each alert fires exactly once.
  7. Add the daily at-risk digest once the per-ticket alerts are quiet and correct.

For the routing that decides who an alert wakes up, the Customer Health Score & Retention Engine escalates critical accounts to Slack and logs to Sheets, and the Review Response Engine handles the response once an agent picks up the breached ticket.

Browse the customer support templates →
Skip the build

The Customer Health Score & Retention Engine ships the scoring-and-escalate spine of this end to end: it scores every customer event in real time, escalates critical accounts to a Slack channel with context, and logs every event to Google Sheets, so the alert-and-log chain is already wired and you add the SLA clock on top. It's part of The Complete n8n Templates Bundle, a one-time lifetime license to the whole catalog plus every template added later, which pays off the moment you run more than one of these support automations.

Get the Customer Health Score Engine →

An SLA alert is only worth building if it lands before the deadline and never repeats itself into noise. Pair this with the tier-climbing logic in How to Build n8n Support Escalation Routing and the classification step in How to Build Support Ticket Triage with n8n and AI for a queue that warns you in time. Mind the business hours. Remember what you said. Let the clock speak once per line it crosses.

Start with the Customer Health Score Engine →
FAQ

Common questions

How does n8n calculate SLA time remaining?
A Schedule trigger reads open tickets, and a Code node computes elapsed time against each ticket's SLA target, then expresses it as a percentage consumed. Subtracting non-business hours makes the clock match how the team actually works, so a ticket opened Friday evening isn't reported as breached on Saturday morning.
How do I stop n8n from re-sending the same SLA alert every run?
Store an alert-state field on each ticket recording the highest threshold already announced. The workflow only alerts when the current threshold exceeds the stored one, then updates it. Each level (75 percent warning, 90 percent breach) fires exactly once instead of repeating on every cron tick.
Can n8n track SLAs without Zendesk?
Yes. The SLA clock needs a created timestamp, a target duration, and a last-known alert state, all of which fit in a Google Sheets row. Zendesk is one source of those fields; a CRM or a plain spreadsheet works the same way. The math doesn't care where the ticket lives.
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