Why webhooks are the right primitive
Individual notifications (email, SMS, push) work fine when one person handles all alerts. They start to break down when:
- Multiple people need to see the same alert
- Alerts need to route differently based on time, severity, or service
- Acknowledgment and resolution should be tracked centrally
- The team coordinates response in a shared channel rather than a 1:1 thread
Webhooks solve all of those by treating the alert as an HTTP POST request to some other system that already handles team coordination. Slack receives the alert and posts it in a channel. PagerDuty receives it and starts an escalation policy. Your custom incident management tool receives it and creates a ticket.
The monitoring service stops being the alerting brain and becomes the detection layer. The receiving system is the brain.
This separation is good. The two jobs (detect failures vs. coordinate response) have different requirements, and the systems built for each are different products.
The basic shape
A webhook is just an HTTP POST request. Your monitoring service POSTs a JSON payload to a URL you provide; the receiving service does whatever it wants with the data.
A minimal alert payload looks like:
POST https://hooks.example.com/incoming/...
Content-Type: application/json
{
"event": "monitor.down",
"monitor": {
"id": "abc123",
"name": "Marketing site",
"url": "https://example.com",
"tags": ["production", "marketing"]
},
"incident": {
"started_at": "2026-08-04T14:32:00Z",
"status": "active",
"regions_failed": ["us-east", "eu-west"],
"error": "HTTP 502 Bad Gateway"
},
"severity": "critical"
}
Different monitoring services use different payload shapes; receiving services have their own expected shapes too. The job of integration is bridging the two.
Most monitoring vendors provide pre-built integrations for the common destinations — point-and-click setup for Slack, PagerDuty, Discord, etc. Generic webhook support is for when you want to wire up something custom.
Slack integration
Slack has incoming webhooks built in. You enable them for a workspace, choose a channel, and Slack gives you a unique URL. Anything POSTed to that URL gets posted to the channel.
Two ways to set this up:
Option 1: Native integration. Most monitoring services have a “Connect to Slack” button that does the OAuth dance and handles message formatting for you. Recommended path.
Option 2: Custom webhook. Configure your monitoring service to POST to Slack’s incoming webhook URL with a message formatted for Slack’s Block Kit. More work, more flexible.
A Slack-formatted webhook payload:
{
"blocks": [
{
"type": "header",
"text": { "type": "plain_text", "text": "🚨 Marketing site is down" }
},
{
"type": "section",
"fields": [
{ "type": "mrkdwn", "text": "*URL:* example.com" },
{ "type": "mrkdwn", "text": "*Error:* HTTP 502" },
{ "type": "mrkdwn", "text": "*Started:* 14:32 UTC" },
{ "type": "mrkdwn", "text": "*Regions:* us-east, eu-west" }
]
},
{
"type": "actions",
"elements": [
{ "type": "button", "text": {"type":"plain_text","text":"Acknowledge"}, "url": "..." },
{ "type": "button", "text": {"type":"plain_text","text":"View incident"}, "url": "..." }
]
}
]
}
Slack messages can include buttons for one-click acknowledgment. Whether your monitoring service supports this depends on the vendor.
Practical patterns for Slack:
- Separate channels for severity levels. Critical alerts go to
#alerts-critical. Warnings go to#alerts-warnings. The warning channel is on mute for most people; the critical channel is loud. - Thread updates. When an incident progresses (started → acknowledged → resolved), post updates as threaded replies on the original alert. Keeps the channel clean.
- Tag the right people. Use Slack user groups (
@on-call) rather than individual user mentions. The on-call rotation is managed in one place.
PagerDuty integration
PagerDuty is purpose-built for incident management. It’s overkill for most small teams and exactly right for teams running production SaaS with on-call rotations.
The webhook flow with PagerDuty:
- Monitoring detects a failure, POSTs a webhook to a PagerDuty integration URL
- PagerDuty creates an incident, opens it in its system, and starts the escalation policy
- The escalation policy notifies the on-call engineer via phone call, SMS, push, etc.
- If the on-call doesn’t acknowledge within N minutes, PagerDuty escalates to the next person
- When the incident is resolved (either by the on-call clicking “resolve” or by a webhook from the monitoring service saying “this cleared”), PagerDuty closes the incident
PagerDuty’s value isn’t the notification — it’s the escalation policy and on-call schedule management. If your team has on-call rotations, PagerDuty is worth the cost (it’s expensive: ~$20/user/month). If you don’t, it’s overkill.
Opsgenie (now part of Atlassian) is a similar product, often cheaper. Both have free tiers worth evaluating.
Practical patterns for PagerDuty:
- One integration per service. Each major component of your system gets its own PagerDuty service. That way escalation policies can be different per service.
- Use the right priority. PagerDuty supports P1–P5 priorities; only P1–P2 should page someone outside business hours.
- Configure auto-resolve. When your monitoring service sees the failure clear, send a “resolve” webhook to close the incident automatically. Manual close-the-loop is friction nobody needs.
Discord integration
Discord webhooks work essentially the same as Slack — enable webhooks on a server, get a URL, configure your monitoring service to POST there.
The main practical difference is how teams use Discord. Slack is dominant in startup-y and tech-company environments; Discord is dominant in gaming/community/indie environments. The features overlap; the conventions are different.
Discord-formatted payload:
{
"embeds": [{
"title": "🚨 Marketing site is down",
"description": "HTTP 502 Bad Gateway",
"color": 15158332,
"fields": [
{ "name": "URL", "value": "example.com", "inline": true },
{ "name": "Regions", "value": "us-east, eu-west", "inline": true },
{ "name": "Started", "value": "14:32 UTC", "inline": true }
],
"footer": { "text": "MyUptimeBot" },
"timestamp": "2026-08-04T14:32:00Z"
}]
}
For Discord-based communities (open-source projects, indie SaaS with a Discord support server), routing alerts to a private staff channel works well. For client-work freelancers using Discord with clients, having a dedicated “incidents” channel for transparency can build trust.
Custom webhooks: when you need them
The pre-built integrations cover 90% of cases. The remaining 10% are situations like:
- You have a custom incident management system
- You want to fan-out alerts to multiple destinations with different formatting
- You want to enrich alerts with additional context before they reach humans (looking up customer impact, adding deploy info)
- You’re routing alerts into a queue for batch processing
The pattern is to point the monitoring service at your own webhook receiver — usually a small serverless function (AWS Lambda, Cloudflare Workers, Vercel Functions, etc.) that:
- Receives the monitoring alert
- Does whatever transformation/enrichment you need
- Forwards to one or more downstream destinations
A reference implementation in 30 lines:
// Cloudflare Worker / generic serverless function
export default {
async fetch(request, env) {
const alert = await request.json();
// Optional: enrich with deploy info
const lastDeploy = await env.KV.get('last-deploy-info');
// Format for each destination
const slackMessage = formatForSlack(alert, lastDeploy);
const pagerDutyEvent = formatForPagerDuty(alert);
// Fan out
await Promise.all([
fetch(env.SLACK_WEBHOOK_URL, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(slackMessage)
}),
fetch(env.PAGERDUTY_EVENTS_URL, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(pagerDutyEvent)
})
]);
return new Response('OK', { status: 200 });
}
};
Cost: free (most serverless free tiers handle this volume easily). Reliability: as good as the underlying serverless platform, which is very good.
Practical patterns across all destinations
A few principles that apply regardless of which destination you’re using:
Idempotency. A monitor that flaps can send the same alert multiple times. Your webhook receiver should de-dupe — most do this automatically via an incident ID or correlation key.
Auto-resolve. Send a resolved event when the monitor recovers. Manual incident close is friction.
Severity routing. Critical, warning, and info alerts should go to different channels or different destinations entirely. Putting everything in one channel trains people to mute the channel.
Context-rich payloads. A useful alert includes the URL, the error, the duration so far, which regions failed, what changed recently (if known), and a link to the monitoring service for more detail. Bare “ALERT: down” messages waste everyone’s time.
Test the webhook before relying on it. Most monitoring services have a “send test event” button. Use it. The day a real incident fires is not the day to discover the webhook is misconfigured.
Reliability of webhook delivery
A subtle gotcha: webhooks are not 100% reliable. The receiving service might be down. The network in between might be slow. The webhook might be rate-limited.
Good monitoring services retry failed webhooks with exponential backoff for several minutes. Bad ones fire once and move on. If your alerting strategy depends on a single webhook destination, find out what your vendor does on failure.
For critical alerts, redundancy matters: send the alert to two destinations. If Slack is down, the SMS still arrives. If PagerDuty is down, the Slack post still happens. The cost is low; the insurance is worth it.
What MyUptimeBot does, plainly
We support outgoing webhooks on all paid plans, with native integrations for Slack, Discord, and standard webhook POST format that can be consumed by any service. PagerDuty integration is on the roadmap.
For teams that need full incident management — escalation policies, on-call rotations, SLO tracking — the right pattern is pairing our detection layer with a dedicated tool (PagerDuty, Opsgenie, Better Stack). We’re the source of the alert; they’re the orchestrator.
For smaller teams, sending alerts directly to a Slack/Discord channel plus a personal channel (SMS or push) is usually enough. The dedicated tools become worth the cost when you have an actual rotation to manage.
The principle: monitoring should detect, not orchestrate. Let it do detection well, and route the output to wherever your team already coordinates response. Webhooks are how you do that cleanly.