Slack Alerting That Scales with On-Call
Part of Platform Engineering
- Observability
- SRE
- Automation
Alert fatigue does not start with too many alerts. It starts with alerts that do not tell you what to do, route to the wrong channel, and page the same person for both a cert expiry and a database failover.
Slack is where modern on-call lives-but Slack is a chat app, not an incident manager. The platform team's job is to design routing, enrichment, and escalation so alerts scale with team growth without scaling noise linearly.
Alert Taxonomy Before Integration
Before wiring Alertmanager to Slack, classify alerts by response expectation. Mixing types in one channel guarantees mute-all behavior.
| Type | Response | Slack destination | Page? |
|---|---|---|---|
| Actionable | Human must act now | #incidents + PagerDuty | Yes |
| Ownership | Team-specific degradation | #team-api-alerts | Maybe |
| Informational | FYI, no immediate action | #platform-feed | No |
| Audit | Compliance trail | #audit-log (read-only bot) | No |
If more than 20% of alerts in #incidents require no action within 24 hours, you have a classification problem-not a Slack problem.
Routing Architecture
Use Alertmanager routes as the source of truth; Slack is a presentation layer. Avoid duplicate routing logic in custom bots.
Prometheus / CloudWatch
│
▼
Alertmanager routes
(severity, team, service labels)
│
├── webhook → Slack (#incidents)
├── webhook → Slack (#team-api)
└── PagerDuty (severity=critical only)
│
▼
Slack workflow: enrich + thread# alertmanager.yml route fragment
route:
receiver: slack-platform
routes:
- match:
severity: critical
receiver: pagerduty-oncall
continue: true
- match:
team: api
receiver: slack-team-api
- match:
severity: info
receiver: slack-feed
receivers:
- name: slack-team-api
slack_configs:
- channel: "#team-api-alerts"
send_resolved: true
title: '{{ .CommonLabels.alertname }}'
text: '{{ .CommonAnnotations.runbook_url }}'Enrichment: Runbooks, Dashboards, and Context
A bare 'HighErrorRate' alert wastes five minutes while on-call searches for the dashboard. Every actionable alert should carry structured annotations.
- runbook_url - link to automated or manual runbook.
- dashboard_url - deep link to Grafana panel with correct variables.
- recent_deploys - injected via Alertmanager template or Slack workflow querying Argo CD API.
- severity and customer_impact - plain language, not just numeric threshold.
# PrometheusRule annotations
annotations:
summary: "API error rate above 1% for 5m"
runbook_url: "https://runbooks.internal/api/high-error-rate"
dashboard_url: "https://grafana.internal/d/api-red?var-env=prod"
impact: "User-facing checkout and course enrollment"Slack Block Kit messages beat plain text for scanability: severity color bar, buttons for ack and runbook, thread for discussion.
Thread Discipline and Incident Hygiene
One alert firing should spawn one thread. Replies in-channel create duplicate conversations and lost context.
- Bot posts root message; all investigation goes in thread.
- Emoji ack (eyes) means investigating-does not replace PagerDuty ack for pages.
- Resolve in Alertmanager triggers resolved message in thread with duration.
- Weekly bot summary: top 10 noisy alerts, MTTA, alerts with no runbook link.
#incidents channel flow ────────────────────── [CRITICAL] RDSReplicaLag - api-db ├── Thread: investigation notes ├── Button: Acknowledge (PagerDuty) ├── Button: Open runbook └── Button: Escalate to platform lead [RESOLVED] after 14m - root cause: batch job
Scaling with On-Call Rotation
When one person carries the pager, Slack DMs feel fine. At three rotations across time zones, you need explicit ownership labels and schedule-aware routing.
- PagerDuty schedule is source of truth; Slack mentions @oncall-api from PD Slack integration.
- Business-hours alerts to team channels; after-hours critical only to page.
- Follow-the-sun handoff message at rotation boundary with open incident summary.
- Per-team alert budgets: more than 5 pages per engineer per week triggers alert review.
Platform team owns routing infrastructure; service teams own alert quality for their rules.
Engineering Takeaways
- Classify alerts by response expectation before choosing Slack channels-actionable vs informational.
- Alertmanager routes are source of truth; Slack is presentation, not a second routing layer.
- Every actionable alert needs runbook_url, dashboard_url, and plain-language impact annotation.
- One alert, one thread-channel noise kills on-call effectiveness faster than alert count.
- Page only critical alerts; route team ownership alerts to team channels without waking people.
- Track alert budget per engineer; chronic noise triggers mandatory alert rule review.
- Weekly noisy alert reports turn Slack history into continuous improvement data.
Trade-offs I Would Consider
Option: Single #alerts channel for everything
- Pros: Simple setup, one place to look, low maintenance.
- Cons: Unusable within months; mute-all culture, wrong responders, no prioritization.
Option: Tiered channels + PagerDuty for critical only
- Pros: Scales with team size, preserves on-call sanity, clear escalation path.
- Cons: More upfront routing design, requires label discipline on metrics and rules.
What I Would Do in Production
Audit all PrometheusRule and CloudWatch alarms: add runbook_url or delete the rule.
Implement Alertmanager routes by team and severity; zero critical alerts to non-paging receivers without continue: true audit.
Deploy Slack bot with Block Kit: ack button, runbook link, auto-thread replies.
Set PagerDuty integration for severity=critical only; everything else stays in Slack channels.
Publish on-call alert budget metric; review top noise contributors in monthly platform meeting.
Run quarterly fire drill: inject test alert, measure time-to-ack and time-to-runbook-open.
FAQ
Q: Should Slack replace PagerDuty?
No. Slack for collaboration and non-urgent alerts; PagerDuty (or equivalent) for wake-up-grade pages with escalation policies and schedule management.
Q: How do we stop duplicate alerts?
Alertmanager inhibition rules, grouping by alertname and cluster, and dedup keys in PagerDuty. Fix the metric before adding more routes.
Q: What about alerts from non-Prometheus sources?
Normalize through Alertmanager webhook adapter or a small routing service that adds standard labels before Slack delivery.
Q: Can we use Slack workflows instead of custom bots?
Yes for simple enrichment and button ack. Complex deploy context and Argo CD queries usually need a lightweight middleware service.
Q: How many channels is too many?
Start with incidents, one feed channel, and one per engineering team. Split further only when daily volume exceeds 50 messages per channel.
Related articles