> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rootly.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Alerts: ingestion, deduplication, grouping, and routing

> How Rootly ingests, deduplicates, groups, and routes alerts from monitoring tools, with links to setup guides for each stage of the alert lifecycle.

export const DedupGroupingWizard = () => {
  const [choice, setChoice] = useState(null);
  const cls = {
    surface: "bg-[#fcfbfa] dark:bg-[#161412]",
    surfaceCard: "bg-white dark:bg-[#161412]",
    border: "border-[#dcd9d7] dark:border-[#4a4741]",
    textPrimary: "text-[#292523] dark:text-[#e7e5e4]",
    textSecondary: "text-[#57534d] dark:text-[#a6a09b]",
    textTertiary: "text-[#6c6761] dark:text-[#87817b]",
    warnBg: "bg-[#fafbd6] dark:bg-[#3e2308]",
    warnBorder: "border-[#f5f299] dark:border-[#724712]",
    warnText: "text-[#7f500c] dark:text-[#f8f8bb]",
    hoverSurface: "hover:bg-[#f3f3fa] dark:hover:bg-[#201d1b]",
    hoverBorder: "hover:border-[#7748f6] dark:hover:border-[#a88bee]",
    focus: "focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[#7748f6] focus-visible:ring-offset-white dark:focus-visible:ring-offset-[#161412]"
  };
  const brandPurple = "#7748f6";
  const options = [{
    id: "same-monitor",
    label: "The same monitor keeps re-firing while the issue is still open",
    example: "Datadog 'High CPU on web-01' alarm fires every minute until we mitigate."
  }, {
    id: "many-monitors",
    label: "Multiple different monitors fire on the same underlying incident",
    example: "Latency, error rate, and DB-health monitors all trip when a service degrades."
  }, {
    id: "both",
    label: "Both happen — same monitor re-fires AND multiple monitors trip together",
    example: "Service is degraded, multiple monitors fire, and each one keeps re-firing."
  }, {
    id: "silent-repage",
    label: "I want guaranteed silent behavior while I'm working on the alert",
    example: "Whatever else is true, do not re-page anyone after the first page goes out."
  }];
  const results = {
    "same-monitor": {
      tool: "Alert Deduplication",
      url: "/alerts/alert-deduplication",
      summary: "Configure deduplication on the Alert Source with a stable per-payload key (JSONPath or alert field). Repeat events with the same key stack onto the existing alert instead of creating new ones.",
      caveat: "Re-page behavior on duplicates can vary by alert source and the existing alert's state. If you need fully deterministic silence, use Alert Grouping instead — it guarantees silent membership for the duration of the time window."
    },
    "many-monitors": {
      tool: "Alert Grouping",
      url: "/alerts/alert-grouping",
      summary: "Build an Alert Group keyed on destination (team / service / escalation policy) + a time window + content matching rules. The first matching alert pages on-call; subsequent matching alerts join silently as members.",
      caveat: null
    },
    both: {
      tool: "Enable both Deduplication and Alert Grouping",
      url: "/alerts/alert-deduplication",
      summary: "Configure source-level Deduplication first — it runs before the alert is even created and collapses same-monitor noise. Then layer Alert Grouping on top to handle different-monitor-but-related noise. The two are complementary.",
      caveat: "Order matters: dedup runs first (at the source level, before alert creation), then grouping runs on whatever survives. After configuring dedup, set up Alert Grouping next."
    },
    "silent-repage": {
      tool: "Alert Grouping",
      url: "/alerts/alert-grouping",
      summary: "Grouping guarantees silent membership for the duration of the time window — once the leader alert pages, subsequent matching alerts join the group silently regardless of source state. This is the most deterministic 'don't page me again' behavior.",
      caveat: "Deduplication might also work for this, but its re-page behavior depends on the source. Use Grouping when you need a guarantee."
    }
  };
  if (choice) {
    const r = results[choice];
    if (!r) {
      return <div className={`my-4 rounded-lg border p-5 ${cls.border} ${cls.surface}`}>
          <div className={`text-sm mb-3 ${cls.textSecondary}`}>
            We couldn't load a recommendation for that selection. Please start over.
          </div>
          <button type="button" onClick={() => setChoice(null)} className={`px-3 py-2 rounded-md text-sm border cursor-pointer transition-colors ${cls.border} ${cls.textSecondary} ${cls.surfaceCard} ${cls.hoverSurface} ${cls.focus}`}>
            ← Start over
          </button>
        </div>;
    }
    return <div className={`my-4 rounded-lg border p-5 border-l-4 ${cls.border} ${cls.surfaceCard}`} style={{
      borderLeftColor: brandPurple
    }} role="status" aria-live="polite">
        <div className="text-xs font-semibold uppercase tracking-wider mb-1" style={{
      color: brandPurple
    }}>
          Recommended
        </div>
        <div className={`text-xl font-semibold mb-3 ${cls.textPrimary}`}>
          {r.tool}
        </div>
        <div className={`text-sm leading-relaxed mb-3 ${cls.textSecondary}`}>
          {r.summary}
        </div>
        {r.caveat && <div className={`text-sm leading-relaxed rounded-md px-3 py-2 mb-3 border ${cls.warnBg} ${cls.warnBorder} ${cls.warnText}`}>
            <strong>Caveat:</strong> {r.caveat}
          </div>}
        <div className="flex items-center gap-3 flex-wrap">
          <a href={r.url} className={`inline-block px-4 py-2 rounded-md text-sm font-medium text-white no-underline hover:opacity-90 transition-opacity ${cls.focus}`} style={{
      backgroundColor: brandPurple
    }}>
            Open the setup guide →
          </a>
          <button type="button" onClick={() => setChoice(null)} className={`px-3 py-2 rounded-md text-sm border cursor-pointer transition-colors ${cls.border} ${cls.textSecondary} ${cls.surfaceCard} ${cls.hoverSurface} ${cls.focus}`}>
            ← Start over
          </button>
        </div>
      </div>;
  }
  return <div className={`my-4 rounded-lg border p-5 ${cls.border} ${cls.surface}`}>
      <div className={`font-semibold mb-1 ${cls.textPrimary}`}>
        Which best describes your alert-noise problem?
      </div>
      <div className={`text-sm mb-4 ${cls.textSecondary}`}>
        Pick the option closest to your situation — we'll point you at the right tool to configure.
      </div>
      <div className="flex flex-col gap-2">
        {options.map(opt => <button key={opt.id} type="button" onClick={() => setChoice(opt.id)} className={`w-full text-left p-3 rounded-md border cursor-pointer transition-colors ${cls.border} ${cls.surfaceCard} ${cls.hoverBorder} ${cls.hoverSurface} ${cls.focus}`}>
            <div className={`text-sm leading-snug ${cls.textPrimary}`}>
              {opt.label}
            </div>
            <span className={`block mt-1 text-xs italic ${cls.textTertiary}`}>
              Example: {opt.example}
            </span>
          </button>)}
      </div>
    </div>;
};

# How Alerts Work

Alerts represent events generated by your users or monitoring and operational tools when something needs attention—like a firing Datadog monitor, a PagerDuty incident, or a Zendesk ticket.

In Rootly:

* Each alert has a **status**:
  * `open`
  * `triggered`
  * `acknowledged`
  * `resolved`
* Alerts can be **linked to incidents**, so responders see the right telemetry and tickets in context.
* Alert records track a **request count** and **last received time**, so you can see how often a condition has fired.

Rootly supports two different kinds of alerts: programmatic and manual.

Programmatic alerts are automatically ingested into Rootly via your Alert Sources, and connected to incidents via workflows, mappings, or manual linking. Manual alerts however are manually created by your users: either to escalate an incident, or page someone ad hoc. This can be done in Rootly's web application, Slack, or the mobile app.

***

# Programmatic Alerts

## Supported Alert Sources

Rootly integrates with many alerting and ticketing tools. Some of the most common include:

| Integration                                                                                               | Trigger                                         |
| --------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
| [PagerDuty](/integrations/pagerduty)                                                                      | When a PagerDuty Incident is created            |
| [Opsgenie](/integrations/opsgenie)                                                                        | When an Opsgenie Incident is created            |
| [Splunk On-Call](https://docs.rootly.com/integrations/victor-ops) ([VictorOps](/integrations/victor-ops)) | When a VictorOps Incident is created            |
| [Datadog](/integrations/datadog)                                                                          | When a Datadog alert is triggered               |
| [Zendesk](/integrations/zendesk)                                                                          | When a Zendesk ticket is created (customizable) |
| [Nobl9](/integrations/nobl9)                                                                              | When an SLO is not satisfied                    |
| [Sentry](/integrations/sentry)                                                                            | When a Sentry alert is triggered                |

Additional alert sources include tools like **Asana, ClickUp, Rollbar, Jira, Honeycomb, ServiceNow, Linear, Grafana, Alertmanager, Google Cloud, CloudWatch, Azure, Splunk, Chronosphere, New Relic, GitLab**, and more—usually via a dedicated integration or generic webhooks.

If your provider is not listed, Rootly can ingest alerts through:

* [**Generic Webhook Alert Sources**](/integrations/generic-webhook-alert-source)

<Note>
  Alert ingestion is rate limited to **50 alerts per minute per source/API key** by default.\
  This limit is **configurable per team**, and higher limits are available for Enterprise customers upon request.
</Note>

***

## Reducing Alert Noise

Rootly offers two complementary noise-reduction tools: **[Alert Deduplication](/alerts/alert-deduplication)** and **[Alert Grouping](/alerts/alert-grouping)**. They solve different problems and can be enabled together. Pick the one that matches your situation:

<DedupGroupingWizard />

***

## Deduplication vs. Alert Grouping

Deduplication and [Alert Grouping](/alerts/alert-grouping) both reduce noise, but they're built for different problems. They can be used together — most large tenants do — but if you only need one, this section helps you pick.

|                                        | **Deduplication**                                                                                                                                                                                                                                   | **Alert Grouping**                                                                                                                                                  |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **The problem it solves**              | The same monitor keeps firing while the underlying condition is still bad                                                                                                                                                                           | Multiple *different* monitors fire on the same underlying incident (latency + error rate + DB health all trip at once)                                              |
| **What it matches on**                 | A stable unique identifier on the payload (JSONPath or alert field)                                                                                                                                                                                 | Destinations (team / service / escalation policy) + a time window + content match rules                                                                             |
| **Scope**                              | Source-level (per Alert Source, keyed dedupe) or team-level (exact-payload suppression — see [Payload-Based Duplicate Suppression](#payload-based-duplicate-suppression))                                                                           | Cross-source — a group rule can span monitors from different sources. **Only routed/paging alerts can join a group** (see [Alert Grouping](/alerts/alert-grouping)) |
| **What happens to the new alert**      | No new alert is created; the existing alert's request count increments and a duplicate event appears on its timeline                                                                                                                                | A new alert is created and joins the existing alert's group as a *member*; the original alert is the *leader*                                                       |
| **Paging behavior**                    | The original page already went out. Repeat events on an unresolved alert do not re-page in the deduped case — but exact re-page behavior depends on the alert source and the alert's state (some sources can re-trigger if the alert state changes) | The leader pages once. Members join silently. No additional pages while the group's time window is open, regardless of how many member alerts arrive                |
| **When the consolidation window ends** | When the existing alert is resolved (the next event with the same key starts a new alert)                                                                                                                                                           | When the group's time window expires, OR when the leader alert is resolved                                                                                          |
| **Best for**                           | "The same alarm keeps re-firing every minute while the issue is open"                                                                                                                                                                               | "Five monitors lit up on the same outage — page me once, attach the others as context"                                                                              |

**Plain-English rule:** If your concern is *one noisy monitor*, use Deduplication. If your concern is *one incident lighting up multiple unrelated monitors*, use Alert Grouping. If your concern is "stop paging me again while I'm working on it" and you want the most deterministic behavior, **Alert Grouping is usually the better fit** — it guarantees silent membership for the duration of the time window, whereas deduplication's re-page behavior can vary by source.

You can enable both. Dedup runs first (at the source level, before the alert is created), so a deduped event never reaches grouping. Grouping then handles the surviving alerts.

***

## Linking Alerts to Incidents

Alerts become most useful when tied directly to incidents.

In Rootly, alerts can be associated with incidents via:

* **Integration mappings and workflows**
  * e.g., “When a PagerDuty incident is created, attach the alert to the corresponding Rootly incident.”
* **Automation logic**
  * e.g., based on service, environment, or alert attributes
* **Manual linking** from the incident or alert views

Once linked, responders can:

* Jump from the incident to the underlying alert(s)
* See how many times the alert fired (via the requests count)
* Use alert details to drive mitigation and follow-up tasks

***

## Best Practices

* **Choose a stable deduplication key**\
  Use identifiers like monitor IDs, incident keys, or ticket IDs—avoid full message text or highly variable fields.
* **Start narrow, then broaden if needed**\
  Begin with conservative dedup rules and relax them as you gain confidence, to avoid accidentally merging unrelated alerts.
* **Link alerts to incidents early**\
  Use workflows to automatically attach alerts to incidents as soon as they are ingested.
* **Watch the request count**\
  A high `×N` count on an alert is a strong signal of ongoing or flapping conditions and can inform severity and prioritization.
* **Tune rate limits for noisy environments**\
  If you know a source can spike, consider increasing the per-source rate limit for that team.

***

# Manual Alerts

Manual alerts are created by users to page other users, teams, services, functionalities, or escalation policies — usually when escalating an incident to another responder or pulling in a subject matter expert from another team. When you manually page a team or service, Rootly kicks off that target's escalation policy, identically to programmatic paging.

For the full guide — including how to narrow the paging picker, the `/rootly escalate` vs `/rootly page` Slack commands, and default alert message templates — see **[Manual Paging](/alerts/manual-paging)**.

***

# Troubleshooting

<AccordionGroup>
  <Accordion title="Alerts aren’t being combined as expected">
    Confirm that **Combine duplicate alerts into one alert** is enabled on the Alert Source and that the **deduplication key path** points to a stable, consistent value.\
    If the key changes between alerts, Rootly treats them as separate alerts.
  </Accordion>

  <Accordion title="I see fewer alerts than my provider shows">
    Often this means deduplication is working as designed.\
    Multiple provider alerts may be mapped to a single Rootly alert, with extra occurrences recorded as **ignored/duplicate requests** on the original alert.
  </Accordion>

  <Accordion title="The alert requests counter isn’t increasing">
    Make sure:

    * Deduplication is configured correctly, **or** payload-based suppression is enabled
    * Incoming payloads actually match the configured dedup key or body\
      If the identifier or body differs, Rootly will create separate alerts instead of incrementing the existing one.
  </Accordion>

  <Accordion title="Alerts are hitting rate limits">
    Rootly enforces a per-team, per-source/API key rate limit (default **50 alerts/minute**).\
    For high-throughput environments, increase the **alerts rate limit per minute** in team settings or contact support for higher Enterprise limits.
  </Accordion>

  <Accordion title="An alert from my tool never appears in Rootly">
    Check:

    * The integration is installed and authenticated
    * The mapping points to the right team or alert source
    * The webhook or outbound configuration is using the correct URL
    * The payload contains all required fields for that integration\
      Also review integration error logs in Rootly for more details.
  </Accordion>
</AccordionGroup>
