Look at almost any uptime monitoring pricing page and SMS is the line that pushes you up a tier: "SMS alerts" with an asterisk, credits that run out mid-incident, or a phone-call feature that starts at a plan several times the price of the monitoring itself. It's priced that way because carriers charge per message, and because SMS has a reputation as the channel that actually wakes you up. The first part is true. The second part is fifteen years out of date.

CronAlert doesn't have a built-in SMS channel, and this article explains why that's rarely a loss, then gives you the three ways to get a text or a phone call anyway: a push notification configured to break through Do Not Disturb (free, and the right default), PagerDuty for real phone calls with escalation ($5/month via CronAlert Pro, plus PagerDuty's own free tier), and a small Cloudflare Worker that turns CronAlert's webhook into Twilio SMS or voice for about a cent per alert. Each comes with the recipe and the honest trade-offs.

First: is a text actually what you want?

The job of a downtime alert at 3 AM is to wake one specific person reliably, tell them what's down, and stop once it's fixed. Score the channels against that:

  • Push notifications arrive in a few seconds, can be exempted from Do Not Disturb and Focus modes on the phone so they sound at night, carry a tap-to-open link to the incident, and cost nothing to send. Their weakness: they need a data connection and an app or PWA installed, and a phone that's off is a phone that's off.
  • SMS works on any phone with a signal, including a shared on-call handset in a drawer. Its weaknesses in 2026: carriers deprioritize automated traffic, messages with links get filtered, delivery can lag minutes on a congested network, most vendors meter it and cut you off after N messages, and it doesn't escalate; if you sleep through it, nothing else happens.
  • Phone calls are the hardest to sleep through and the only channel that naturally escalates ("no answer, call the next person"). They're also the most disruptive, which is why they belong behind a policy: call after a push went unacknowledged, or only for the monitors that matter at night.

For one person or a small team, the honest ranking is push first, phone call as escalation, SMS for the specific cases where the other two can't reach you. If that's you, start with the next section and you may never need the rest.

Option 1: push notifications that break through Do Not Disturb (free)

CronAlert sends web push notifications to iPhone, Android, Mac, and Windows on the free plan. The setup is a few taps: add CronAlert to your home screen (required on iOS), enable push in the app's settings, and allow notifications. The part people miss is configuring the phone so the notification is allowed to wake you. Web push can't mark itself urgent; the exception has to be yours. On iOS, open Settings, Notifications, find the CronAlert home-screen app, and turn on sound; then edit your Sleep Focus and add it under allowed apps so it rings through. On Android, open the notification channel for CronAlert (under the browser's or the installed app's notification settings), set its importance to the highest level, and turn on "Override Do Not Disturb" where the OEM offers it. Full walkthroughs: iOS, Android, Mac, Windows.

Then send yourself a test alert with the phone face-down on Do Not Disturb. If it sounds, you've built the wake-up channel most people are paying $30/month for. If it doesn't, fix the Focus exception before doing anything else in this article; a Twilio relay pointing at a phone that's silenced has the same problem.

Option 2: PagerDuty for phone calls and escalation (Pro)

If more than one person can be paged, or you want a phone call only after a push goes unacknowledged, the right tool is an incident manager, and PagerDuty is the one CronAlert speaks natively. The PagerDuty channel is on the Pro plan at $5/month. CronAlert triggers a PagerDuty incident when a monitor goes down and resolves it when the monitor recovers; PagerDuty handles who gets notified, how, and what happens if they don't respond.

Inside PagerDuty, your notification rules can be "push immediately, SMS after 2 minutes, phone call after 5, then escalate to the next person on the schedule." Phone and SMS are PagerDuty's to deliver, on its own numbers and registrations, so you skip the carrier paperwork below entirely. As of 2026, PagerDuty's free tier supports a small team with a monthly cap on SMS and phone notifications; check their current limits, but for a team seeing a few incidents a month it's generally enough. The combination, $5 for CronAlert Pro plus PagerDuty's free tier, gets you real phone calls with escalation for less than most monitoring vendors charge for SMS alone. The on-call rotation guide covers setting up the schedule and escalation policy.

Opsgenie and Splunk On-Call users: CronAlert's webhook channel plus their inbound integrations does the same job; see Opsgenie and Splunk On-Call.

Option 3: Twilio SMS or voice via a webhook relay (free channel, ~1¢ per alert)

For an individual who wants an actual text, or a team with a compliance reason for SMS, the webhook channel (free plan) plus a tiny relay gives you Twilio texts or calls at Twilio's raw price, with no vendor markup and no credit cap. CronAlert POSTs a JSON payload on monitor.down and monitor.recovered; the relay reshapes it into a Twilio API call. It runs on a Cloudflare Worker's free tier and is about twenty lines.

Twilio setup, including the part that bites

  1. Create a Twilio account and buy a phone number with SMS (and voice, if you want calls). About a dollar a month.
  2. If you're sending to US numbers, register the number. Since carriers began enforcing A2P 10DLC, unregistered application traffic from a standard local number is filtered heavily or blocked. Register a brand and a campaign (a low-volume "sole proprietor" registration exists for individuals) or use a toll-free number and complete toll-free verification. Either takes days, not minutes, so do it before you need it. Alerts to your own number still count as A2P. Other countries have their own rules; Twilio's docs list them per country.
  3. Note your Account SID, an Auth Token (or an API key), and the number.
  4. Pick a webhook signing secret and note it; you'll enter it in CronAlert and the Worker.

The Worker

// wrangler secrets: TWILIO_SID, TWILIO_TOKEN, TWILIO_FROM, ALERT_TO, CRONALERT_SECRET
export default {
  async fetch(req, env) {
    if (req.method !== "POST") return new Response("ok");
    const raw = await req.text();
    if (!(await verify(raw, req.headers.get("X-CronAlert-Signature"), env.CRONALERT_SECRET)))
      return new Response("bad signature", { status: 401 });

    const a = JSON.parse(raw);
    const down = a.event === "monitor.down";
    const body = down
      ? `DOWN: ${a.monitor.name} (${a.check?.statusCode ?? a.check?.errorMessage ?? "no response"})`
      : `RECOVERED: ${a.monitor.name} after ${minutes(a.incident)} min`;

    const auth = "Basic " + btoa(`${env.TWILIO_SID}:${env.TWILIO_TOKEN}`);
    const form = new URLSearchParams({ To: env.ALERT_TO, From: env.TWILIO_FROM, Body: body });
    const r = await fetch(`https://api.twilio.com/2010-04-01/Accounts/${env.TWILIO_SID}/Messages.json`, {
      method: "POST", headers: { Authorization: auth }, body: form,
    });
    return new Response(r.ok ? "sent" : await r.text(), { status: r.ok ? 200 : 502 });
  },
};

function minutes(incident) {
  if (!incident?.startedAt || !incident?.resolvedAt) return "?";
  return Math.round((new Date(incident.resolvedAt) - new Date(incident.startedAt)) / 60000);
}

async function verify(raw, header, secret) {
  if (!header || !secret) return false;
  const key = await crypto.subtle.importKey("raw", new TextEncoder().encode(secret),
    { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
  const sig = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(raw));
  const hex = [...new Uint8Array(sig)].map(b => b.toString(16).padStart(2, "0")).join("");
  if (hex.length !== header.length) return false;
  const enc = new TextEncoder();
  return crypto.subtle.timingSafeEqual(enc.encode(hex), enc.encode(header));  // Workers-only helper
}

Deploy with wrangler deploy, set the five secrets with wrangler secret put, then in CronAlert create a webhook alert channel with the Worker's URL and the same signing secret. The webhook channel guide documents the full payload and the X-CronAlert-Signature header. Keep the message short and free of links: multi-segment texts cost more, and links are the fastest way to get filtered.

Making it call instead

Swap the Messages endpoint for Calls and pass inline TwiML so Twilio reads the alert aloud:

const say = `<Response><Say>${body.replace(/[<>&]/g, "")}. Repeating. ${body.replace(/[<>&]/g, "")}</Say></Response>`;
const form = new URLSearchParams({ To: env.ALERT_TO, From: env.TWILIO_FROM, Twiml: say });
await fetch(`https://api.twilio.com/2010-04-01/Accounts/${env.TWILIO_SID}/Calls.json`, { method: "POST", headers: { Authorization: auth }, body: form });

Only call on monitor.down; nobody wants a 3 AM call to hear that things are fine. A few cents per call as of 2026. Note that this has no acknowledgement and no escalation: if you don't pick up, that's the end of it. That's the line where PagerDuty stops being optional.

Two design notes

  • Alert channels are team-wide. Every enabled channel receives every alert, so the Worker will text you for every monitor. If only a few monitors deserve a text, filter on a.monitor.name (a naming prefix like [page] works well) and return 200 without sending for the rest.
  • Keep a second channel. Webhook delivery is a single POST; if the Worker or Twilio is having a bad moment, the text doesn't go out. Leave email and push enabled too. The point of SMS is to be the channel that works when others don't, not the only one.

What each option costs

RouteCronAlert planOther costEscalationBest for
Push, time-sensitiveFreeNoneNoEveryone, as the default
PagerDuty channelPro, $5/moPagerDuty free tier (capped), paid from ~$21/user/moYes: push, SMS, call, next personTeams; anyone who wants calls
Twilio SMS via webhookFree~1¢/msg + ~$1/mo number, as of 2026NoIndividuals; shared on-call phone; SMS policy
Twilio voice via webhookFreeFew cents/call, as of 2026NoIndividuals who sleep through push
Telegram channelPro, $5/moNoneNoCustom loud notification sound per chat; works over data

For comparison, SMS on the major monitoring vendors' plans typically means a mid or upper tier plus a credit pool. Our UptimeRobot comparison and Pingdom comparison have the current numbers; the pattern is that you pay for monitoring you don't need to get a channel that costs a penny at source.

Frequently asked questions

Does CronAlert send SMS?

Not natively. Use time-sensitive push (free), PagerDuty (Pro) for calls and escalation, or a webhook relay to Twilio for raw-cost SMS and voice.

Is SMS more reliable than push?

Not in most places anymore. Push with a Do Not Disturb exception is faster, richer, and free. SMS wins with no data coverage, a shared handset, or a policy requirement.

Why does my Twilio text never arrive?

Almost always US A2P 10DLC or toll-free registration. Unregistered application traffic is filtered. Register first, and keep links out of the message.

How do I get a phone call when the site goes down?

PagerDuty via the Pro channel for a team (with escalation), or the Twilio voice variant of the Worker for an individual.

Can I text only for certain monitors?

Yes: filter in the Worker on the monitor's name. Channels themselves are team-wide.

Pay a penny, not a tier

The wake-up channel is the last mile of monitoring, and it shouldn't be the thing that decides which plan you're on. Set up push with a Do Not Disturb exception tonight and test it face-down. If you're a team, add PagerDuty for calls and escalation. If you want a literal text, the Worker above sends one for about a cent. Start with the free plan, add your channels, and run a fire drill. Related reading: avoiding alert fatigue, incident response for small teams, and Telegram alerts.