Notification policies (also called routing policies) determine how alerts are routed to contact points based on labels. They provide flexible routing logic with support for grouping, timing, and muting.
Policy Structure
Notification policies form a tree structure where alerts are matched against routes:
interface FormAmRoute {
id : string ;
name ?: string ; // Named route identifier
// Matching
object_matchers : MatcherFieldValue [];
continue : boolean ; // Continue to next sibling routes
// Destination
receiver : string ; // Contact point name
// Grouping
overrideGrouping : boolean ;
groupBy ?: string []; // Labels to group by
// Timing
overrideTimings : boolean ;
groupWaitValue : string ; // Wait before sending first notification
groupIntervalValue : string ; // Wait before sending updates
repeatIntervalValue : string ; // Wait before repeating notifications
// Muting
muteTimeIntervals : string []; // When not to send
activeTimeIntervals : string []; // When to send
// Nested routes
routes : FormAmRoute [];
}
Root Route
Every notification policy tree has a root route that acts as the default:
{
receiver : 'default-contact-point' ,
groupBy : [ 'alertname' , 'grafana_folder' ],
groupWaitValue : '30s' ,
groupIntervalValue : '5m' ,
repeatIntervalValue : '4h' ,
routes : [
// Child routes...
]
}
The root route:
Has no matchers (matches all alerts)
Cannot be deleted
Provides default timing and grouping
Acts as fallback when no child routes match
Label Matchers
Matchers determine which alerts a route handles:
Exact Match
Not Equal
Regex Match
Regex Not Match
{
name : 'severity' ,
operator : '=' ,
value : 'critical'
}
// Matches: severity="critical"
Grouping
Grouping combines related alerts into single notifications:
Group By Labels
groupBy : [ 'alertname' , 'cluster' , 'service' ]
Alerts with the same values for these labels are grouped together:
Alert 1: {alertname="HighCPU", cluster="prod", service="api"}
Alert 2: {alertname="HighCPU", cluster="prod", service="api"}
Alert 3: {alertname="HighCPU", cluster="prod", service="web"}
Result:
- Group 1: [Alert 1, Alert 2] → Single notification
- Group 2: [Alert 3] → Separate notification
Special Grouping
groupBy : [ '...' ] // Single group (all alerts together)
Timing Controls
Group Wait
Wait time before sending the first notification for a new group:
Allows collecting multiple alerts before sending.
Group Interval
Wait time before sending updates about existing groups:
Controls how often you receive updates when alerts are added/resolved in a group.
Repeat Interval
Wait time before resending a notification for the same group:
repeatIntervalValue : '4h'
Prevents notification spam for ongoing incidents.
Timing hierarchy:
Child routes can override parent timings if overrideTimings: true
If not overridden, parent timings are inherited
Root route provides defaults for the entire tree
Continue Flag
The continue flag controls routing behavior:
{
object_matchers : [
{ name: 'severity' , operator: '=' , value: 'critical' }
],
receiver : 'pagerduty' ,
continue : true , // Also check sibling routes
routes : []
}
Without Continue (false)
Alert matches → Route to contact point → Stop processing
With Continue (true)
Alert matches → Route to contact point → Continue to next sibling route
Mute Timings
Mute timings suppress notifications during specific time periods:
Mute Time Intervals
muteTimeIntervals : [ 'business-hours' , 'weekends' ]
Notifications are blocked during these intervals.
Active Time Intervals
activeTimeIntervals : [ 'on-call-hours' ]
Notifications are allowed only during these intervals.
Time intervals are defined separately and referenced by name in routes.
See the Mute Timings documentation for details on creating time intervals.
Named Routes
Routes can be named for easier management:
{
name : 'critical-alerts-policy' ,
object_matchers : [
{ name: 'severity' , operator: '=' , value: 'critical' }
],
receiver : 'pagerduty'
}
Policy Examples
Multi-Tier Routing
{
receiver : 'default' ,
groupBy : [ 'alertname' ],
routes : [
{
// Critical alerts to PagerDuty
object_matchers: [
{ name: 'severity' , operator: '=' , value: 'critical' }
],
receiver: 'pagerduty' ,
groupWaitValue: '10s' ,
repeatIntervalValue: '1h'
},
{
// Team-based routing
object_matchers: [
{ name: 'team' , operator: '=' , value: 'backend' }
],
receiver: 'backend-slack' ,
routes: [
{
// Backend + Critical → Both channels
object_matchers: [
{ name: 'severity' , operator: '=' , value: 'critical' }
],
receiver: 'backend-oncall' ,
continue: true // Also send to backend-slack
}
]
},
{
// Frontend team
object_matchers: [
{ name: 'team' , operator: '=' , value: 'frontend' }
],
receiver: 'frontend-slack'
}
]
}
Environment-Based Routing
{
receiver : 'default' ,
routes : [
{
object_matchers: [
{ name: 'environment' , operator: '=' , value: 'production' }
],
receiver: 'prod-alerts' ,
muteTimeIntervals: [ 'maintenance-window' ]
},
{
object_matchers: [
{ name: 'environment' , operator: '=~' , value: 'staging|dev' }
],
receiver: 'non-prod-alerts' ,
repeatIntervalValue: '12h' // Less frequent for non-prod
}
]
}
Auto-Generated Routes
Grafana automatically generates routes for alert rules with inline notification settings:
Alert Rule with Notifications
Generated Route
{
title : 'High CPU' ,
notificationSettings : {
contactPointRouting : {
receiver : 'ops-team' ,
groupBy : [ 'instance' ],
groupWait : '30s'
}
}
}
Auto-generated routes:
Are managed by Grafana
Cannot be manually edited
Are updated when rule notification settings change
Use special __grafana_* labels for matching
Backend Configuration
Route Configuration
Object Matcher
// Location: pkg/services/ngalert/notifier/alertmanager_config.go
type Route struct {
Receiver string
GroupByStr [] string
Match map [ string ] string
MatchRE map [ string ] string
ObjectMatchers [] ObjectMatcher
Continue bool
Routes [] * Route
GroupWait * time . Duration
GroupInterval * time . Duration
RepeatInterval * time . Duration
MuteTimeIntervals [] string
ActiveTimeIntervals [] string
}
Validation Rules
Receiver Exists
Referenced contact point must exist
Time Intervals Exist
Mute/active time intervals must be defined
Valid Matchers
Matchers must have valid regex patterns
No Circular Routes
Routes cannot reference themselves
Timing Constraints
repeatInterval ≥ groupInterval
Best Practices
Match on stable, meaningful labels like team, service, severity rather than dynamic values.
Group by labels that represent a single incident (e.g., alertname, cluster, service).
groupWait: 30s-1m for collecting related alerts
groupInterval: 5m for update frequency
repeatInterval: 4h-12h to avoid notification fatigue
Only use continue: true when alerts truly need multiple destinations. It can cause notification duplication.
Use the notification policy preview to verify routing before deploying.
Contact Points Configure notification destinations
Alert Rules Create rules that generate alerts
Silences Temporarily mute notifications
Overview Understand the alerting architecture