Skip to main content
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:
{
  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:
groupWaitValue: '30s'
Allows collecting multiple alerts before sending.

Group Interval

Wait time before sending updates about existing groups:
groupIntervalValue: '5m'
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: []
}
1

Without Continue (false)

Alert matches → Route to contact point → Stop processing
2

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:
{
  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

// 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

1

Receiver Exists

Referenced contact point must exist
2

Time Intervals Exist

Mute/active time intervals must be defined
3

Valid Matchers

Matchers must have valid regex patterns
4

No Circular Routes

Routes cannot reference themselves
5

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