Most Slack alerts fail in one of two ways: they contain too much information and people skim past them, or they contain too little and people don’t know what to do. Getting the balance right isn’t hard once you have a clear template to work from.
Here’s the anatomy of an alert that works.
The template
A good Slack alert has five parts, in this order:
[ICON] HEADLINE
Context line 1
Context line 2 (optional)
[PRIMARY ACTION BUTTON] [secondary link]
That’s it. Let’s go through each part.
1. Icon + Headline
The icon is a single emoji. Its job is to create a visual scan target and communicate severity at a glance. Pick a system and use it consistently:
- 🔴 Critical — needs immediate response
- 🟡 Warning — needs attention soon
- 🟢 Resolved — was a problem, now isn’t
- 🔵 Info — FYI, no action needed
The headline follows immediately on the same line (or a header block directly after). It should be:
- Bold or a header block: not body text
- Specific: “Payment processor timeout” not “Error occurred”
- Under 10 words: if you can’t summarize it in 10 words, you haven’t understood it yet
Bad: An error has occurred in the system
Good: 🔴 Stripe webhook processing failed
2. Context (1–2 lines)
This is where you answer the two questions everyone has when they see an alert: how bad is it and what do I need to know to act on it.
Two lines maximum. Include:
- Magnitude or scope (how many affected, what percentage, over what time window)
- The relevant identifier (which service, which customer, which region)
- Anything that narrows down cause or urgency
Bad: There was a problem with payments.
Good: 14 failed webhooks in the last 5 min · Event: payment.succeeded · All from the same endpoint
Don’t include everything you know. Include the things that change what someone does next.
3. Primary action button
One button. It goes directly to the thing a person needs to see or do to handle the alert. Not to the app home page. Not to a generic dashboard. To the specific record, incident, or tool relevant to this exact alert.
Label the button with the action, not the destination:
- “View incident” not “Datadog”
- “Review request” not “Open Jira”
- “Acknowledge” not “OK”
If acknowledging or taking action can happen directly in Slack, great. Use an interactive button that updates the message when clicked. If it requires a web UI, link there directly.
4. Secondary link (optional)
One line in a context block below the button. This is for runbooks, related docs, or secondary resources. Not everyone needs it, but it’s useful to have.
Format: 📖 Runbook · 🔗 Related issue · 📊 Dashboard
Keep it to a single line. If you have more than three links, you have too many.
What a bad alert looks like
Here’s a common real-world alert:
ALERT NOTIFICATION
Service: payment-service
Environment: production
Error: WebhookProcessingException: Unable to process incoming webhook event
Stack trace: [500 lines pasted here]
Time: 2025-04-12T14:32:01Z
Priority: HIGH
Tags: payment, webhook, production
Assigned: on-call
Please investigate immediately.
Problems: no visual hierarchy, buried context, no direct action, stack trace in a Slack message. The person reading this knows there’s a problem but doesn’t know what to do first.
What a good alert looks like
🔴 Stripe webhook processing failed
14 events unprocessed in last 5 min · payment.succeeded · us-east-1
[View failing events →] 📖 Runbook
One read, immediate action. The header tells you what happened. The context tells you scale and scope. The button takes you where you need to go.
The two-message pattern for incidents
For incidents that evolve over time, use two messages:
- The trigger message: sent when the alert fires, with the primary CTA
- The update message (edit the original): when status changes, updated with new context and a resolved state when it clears
Don’t post a new message for every status update. Edit the original. This keeps the channel clean and gives people a single thread to follow.
The fastest way to feel what a good Slack alert actually looks like is to build one. LithoBlocks gives you a visual canvas where you drag in blocks, type real content, and see the rendered message instantly: no JSON, no deploy cycle. When you’re ready to connect real data, you configure the template’s variables and fire your payload to a webhook. The gap between “this looks right” and “this is live in Slack” is much smaller than you’d expect. Try it free →