<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[FluidifyAI]]></title><description><![CDATA[FluidifyAI]]></description><link>https://fluidifyai.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6a9a8936c61f07a75e33caea/3db3414f-8be4-4976-9aa7-072584a61c3f.png</url><title>FluidifyAI</title><link>https://fluidifyai.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 20 Sep 2026 08:54:25 GMT</lastBuildDate><atom:link href="https://fluidifyai.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Escalation Policies as Code: On-Call Rotations in Git]]></title><description><![CDATA[Cross-posted from the Fluidify blog.
Key takeaways

Treating on-call schedules and escalation policies as version-controlled config instead of editing them only in a vendor UI gets you code review, a ]]></description><link>https://fluidifyai.hashnode.dev/escalation-policies-as-code-on-call-rotations-in-git</link><guid isPermaLink="true">https://fluidifyai.hashnode.dev/escalation-policies-as-code-on-call-rotations-in-git</guid><category><![CDATA[oncall]]></category><category><![CDATA[Devops]]></category><category><![CDATA[SRE]]></category><dc:creator><![CDATA[Yathartha Shekhar]]></dc:creator><pubDate>Fri, 18 Sep 2026 06:29:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a9a8936c61f07a75e33caea/4d8dd51b-9669-460e-813e-c2638a38d9d6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Cross-posted from</em> <a href="https://fluidify.ai/blog/escalation-policies-as-code-on-call-rotations-in-git"><em>the Fluidify blog</em></a><em>.</em></p>
<h2>Key takeaways</h2>
<ul>
<li><p>Treating on-call schedules and escalation policies as version-controlled config instead of editing them only in a vendor UI gets you code review, a diff for every change, an audit trail, and the ability to rebuild the entire on-call setup from a git checkout.</p>
</li>
<li><p>The building blocks exist today (Terraform providers for the major platforms, or a sync script against a REST API), but almost nothing lets you simulate a policy change against real traffic before it's live, which is the actual risk this pattern is trying to manage.</p>
</li>
</ul>
<h2>Why on-call config ends up as tribal knowledge</h2>
<p>Ask most teams who's allowed to change an escalation policy, and the honest answer is "whoever has admin access and remembers to." The policy that decides who gets woken up at 3 a.m., and how fast, typically lives entirely inside a vendor's web UI: click into a policy, adjust a timeout, save. No review, no diff, no record of why the timeout went from five minutes to ten, and no way to see what the policy looked like six months ago short of asking whoever made the change, if they still remember.</p>
<p>This is the same problem infrastructure had before Terraform: configuration that only exists as the current state of a system, changeable by anyone with access, with history that lives in people's memory instead of a repository. The fix there was treating infrastructure as code. The same fix applies to on-call config, and for the same reason: escalation policies and schedules are operational logic, not administrative settings, and operational logic that can silently change without review is a real risk during an actual incident, and a quiet contributor to <a href="https://fluidify.ai/blog/why-alert-fatigue-survives-every-tooling-migration">alert fatigue</a> months later when nobody remembers why a timeout is set the way it is.</p>
<h2>The pattern</h2>
<p>The shape is the same as any other infrastructure-as-code setup: a directory of declarative files, a tool that reconciles them against the live system, and a CI pipeline that runs that tool on merge.</p>
<pre><code class="language-plaintext">oncall/
  schedules/
    payments-primary.yaml
    payments-secondary.yaml
    infra-oncall.yaml
  escalation-policies/
    payments-outage.yaml
    infra-warning.yaml
  integrations/
    prometheus-payments.yaml
    cloudwatch-infra.yaml
</code></pre>
<p>A schedule file might look like:</p>
<pre><code class="language-yaml"># schedules/payments-primary.yaml
name: payments-primary
timezone: America/New_York
rotation:
  type: weekly
  handoff: monday 09:00
participants:
  - alice@company.com
  - bob@company.com
  - carla@company.com
overrides:
  - date: 2026-12-24
    user: dave@company.com
    reason: holiday coverage swap
</code></pre>
<p>And an escalation policy:</p>
<pre><code class="language-yaml"># escalation-policies/payments-outage.yaml
name: payments-outage
severity: critical
steps:
  - after: 0m
    notify: schedule:payments-primary
  - after: 5m
    notify: schedule:payments-secondary
  - after: 15m
    notify: user:eng-manager@company.com
    channel: phone
</code></pre>
<p>Nothing here is exotic. It's the same declarative-config idea applied to a domain that mostly hasn't gotten it yet.</p>
<h2>What you actually gain</h2>
<p><strong>Review before it's live:</strong> A change to a critical escalation policy goes through a pull request like any other production change. A reviewer can catch "this removes the secondary on-call from the payments policy" before it ships, not after an incident reveals it.</p>
<p><strong>A real audit trail:</strong> <code>git blame</code> on an escalation policy answers "who changed this and why" in one command, with the linked PR and its discussion attached, instead of a support ticket to the vendor asking for change history.</p>
<p><strong>Rollback:</strong> Revert the commit, re-apply, done. No hunting through a UI trying to remember what the settings used to be.</p>
<p><strong>Disaster recovery for the on-call config itself:</strong> If the on-call platform loses data or an account gets locked out, the entire schedule and escalation setup can be rebuilt from a git checkout, instead of reconstructed from memory during an outage, which is a genuinely bad time to be reconstructing your escalation policies.</p>
<h2>What's still missing</h2>
<p>The gap in this pattern today isn't tooling to declare the config, it's tooling to validate it before it's live. Terraform can plan a diff and show you what will change, but it can't tell you that a proposed escalation policy would have caused an on-call engineer to get skipped during last month's actual incident. Policy simulation, replaying a set of historical alerts against a proposed policy change and showing who would have been paged and when, is close to nonexistent across the ecosystem right now.</p>
<p>The other open problem is drift. If someone edits a schedule directly in the vendor UI during an incident (which will happen, and should be allowed to happen, because the incident doesn't wait for a PR to merge), the git state and the live state disagree until someone reconciles them. Few setups have automated drift detection for on-call config the way they do for infrastructure; most rely on someone noticing during the next <code>terraform plan</code> equivalent.</p>
<h2>Existing building blocks</h2>
<p>You don't have to build this from scratch. Terraform has official or community providers for several on-call and incident platforms, letting you declare schedules and escalation policies as Terraform resources and manage them through a normal <code>plan</code>/<code>apply</code> workflow. Where a provider doesn't exist or doesn't cover something you need, the fallback is a sync script: read the YAML, diff it against the platform's REST or GraphQL API, apply the difference, run it in CI on merge to <code>main</code>. It's less polished than a proper provider but gets you the review-and-audit-trail benefits, which are most of the point.</p>
<p>If you're evaluating on-call tools with this pattern in mind, the thing to check isn't whether a Terraform provider already exists for it; those get built or abandoned constantly. Check whether the platform exposes full API coverage over schedules, escalation policies, and integrations, and whether you can inspect the underlying data model directly if you're self-hosting it. An API-complete, self-hostable platform is one you can always build the sync layer for yourself, provider or not. That's part of why we designed <a href="https://fluidify.ai/regen">FluidifyAI Regen</a> as open-source and API-first, with the <a href="https://github.com/FluidifyAI/">source and API reference on GitHub</a>: the config-as-code layer on top is something a team can build, even before a dedicated integration exists.</p>
<p>If you haven't settled on a platform yet, our rundown of <a href="https://fluidify.ai/blog/10-best-open-source-oncall-management-tools">open-source on-call tools</a> is worth a read before you pick one to build this pattern on top of.</p>
<h2>FAQ</h2>
<p><strong>Do we need a custom sync script if a Terraform provider already exists?</strong> No, use the provider. It's more mature, handles state tracking, and you get <code>terraform plan</code> for free. Reach for a sync script only when no provider covers what you need.</p>
<p><strong>What about changes made during an actual incident?</strong> Let them happen directly in the tool. Reconcile afterward: either update the git source to match what was done live, or revert the live change back to the declared state once the incident is over, whichever is correct for that specific change.</p>
<p><strong>Is this worth it for a five-person team?</strong> The audit trail and rollback value scale with team size and policy complexity, but even a small team benefits from "why does this escalation policy skip Tuesdays" having an answer in git history instead of living in one person's head.</p>
<h2>Where this is heading</h2>
<p>Policy simulation is the missing piece that would make this pattern complete: replay real alert history against a proposed change and see the difference before merging, the same way a <code>terraform plan</code> shows infrastructure diff before <code>apply</code>. Nobody has shipped this well yet across the ecosystem. It's the natural next step for whichever platform builds it first.</p>
]]></content:encoded></item><item><title><![CDATA[Why Alert Fatigue Survives Every Tooling Migration]]></title><description><![CDATA[Cross-posted from the Fluidify blog
Every few years, a team gets tired of drowning in pages and migrates to a new on-call tool. The rollout goes fine. Schedules import cleanly, integrations reconnect,]]></description><link>https://fluidifyai.hashnode.dev/why-alert-fatigue-survives-every-tooling-migration</link><guid isPermaLink="true">https://fluidifyai.hashnode.dev/why-alert-fatigue-survives-every-tooling-migration</guid><category><![CDATA[Devops]]></category><category><![CDATA[oncall]]></category><category><![CDATA[alerting]]></category><dc:creator><![CDATA[Yathartha Shekhar]]></dc:creator><pubDate>Mon, 14 Sep 2026 11:51:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a9a8936c61f07a75e33caea/68310208-7ee9-4b9f-8505-f9ccbb61ce77.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Cross-posted from</em> <a href="https://fluidify.ai/blog/why-alert-fatigue-survives-every-tooling-migration"><em>the Fluidify blog</em></a></p>
<p>Every few years, a team gets tired of drowning in pages and migrates to a new on-call tool. The rollout goes fine. Schedules import cleanly, integrations reconnect, everyone gets a shiny new mobile app. Then, somewhere between four and twelve weeks later, the same on-call engineer who pushed for the migration is back to muting notifications at 2 a.m. and triaging the same noisy alert they were triaging on the old platform.</p>
<p>This isn't a failure of the new tool. It's what happens when a team changes where the alerts land without changing what causes them to fire in the first place. The rules that produced fatigue on the old system, which alerts get created, how they escalate, who they wake up, come across in the migration as faithfully as the schedules do. A new UI on top of the same rules produces the same outcome with a different logo.</p>
<h2>What actually causes alert fatigue</h2>
<p>Three root causes show up in almost every team that reports fatigue, regardless of which tool they're on:</p>
<p><strong>Noisy sources with no classification layer.</strong> Most alerting pipelines treat every signal from Prometheus, CloudWatch, or a health check as equally worth a human's attention. A flapping check that recovers in ninety seconds pages the same way a full outage does. Without deduplication and severity classification at the point alerts are generated, the on-call engineer becomes the classification layer, by hand, every single time.</p>
<p><strong>Escalation policies that don't differentiate urgency.</strong> A five-minute escalation timeout makes sense for a payment outage. It does not make sense for a disk-usage warning that can wait until morning. When every alert type shares one escalation policy, either the urgent stuff waits too long or the routine stuff interrupts sleep, and teams routinely get this backwards in both directions on the same policy.</p>
<p><strong>No owner for alert hygiene.</strong> Someone has to look at the alerts that fired last week, decide which ones were useful, and either fix, downgrade, or delete the ones that weren't. In most teams, nobody owns this. It falls to whoever happens to be on-call when they get frustrated enough, which means the noisy alert survives until someone has a bad week and finally kills it out of spite. That's not a process, and it doesn't scale.</p>
<h2>Why a new tool doesn't fix any of the three</h2>
<p>None of those three causes live in the vendor. Classification, escalation policy design, and hygiene ownership are decisions a team makes and re-makes, and a tool migration is exactly the moment those decisions get carried over unexamined, because reproducing the existing setup quickly is the whole point of a smooth migration. The team optimizes for "nothing broke" and, in doing so, optimizes for "nothing changed," including the parts that were broken.</p>
<p>The tools also look similar enough on this specific axis that switching between them rarely forces the issue. Every mainstream on-call platform supports severity levels, deduplication rules, and tiered escalation. The gap isn't feature availability. It's that configuring those features well takes an audit most teams skip during a migration.</p>
<p>If a migration is already on the table, it's worth doing the audit below before comparing vendors, not after.</p>
<h2>What actually works</h2>
<p>The interventions that measurably reduce fatigue touch the three root causes directly, independent of vendor:</p>
<p><strong>Classify and deduplicate at the source, not at the human.</strong> Group alerts from the same root cause into one notification. Suppress known-flapping checks instead of paging on every transition. This is configuration work on the monitoring side (Alertmanager routing rules, Grafana notification policies) as much as the on-call tool.</p>
<p><strong>Match escalation speed to actual urgency, per alert type, not per team.</strong> A payment-path outage and a disk-warning should never share an escalation policy. Once that logic is right, managing it as version-controlled config instead of a vendor UI setting is what keeps it from drifting back.</p>
<p><strong>Name an owner for alert hygiene, and give them a recurring slot.</strong> Someone reviews the last week or month of pages, tags what was noise, and has the authority to retune or delete rules without three approvals.</p>
<p><strong>Close the loop after every incident.</strong> If a postmortem doesn't produce a concrete change to an alert rule or escalation policy when the alert was part of the problem, the same failure mode reappears with the label "known issue" attached to it.</p>
<h2>A 30-day exercise that costs nothing</h2>
<p>Before any team migrates on-call tools to solve fatigue, it's worth running this against the current one:</p>
<ol>
<li><p>Pull every page from the last 30 days, grouped by alert rule.</p>
</li>
<li><p>For each rule, tag it: actionable, informational (nice to know, didn't need a wake-up), or noise (should never have paged).</p>
</li>
<li><p>For anything tagged noise, delete the rule, add deduplication, or move it off the paging path entirely.</p>
</li>
<li><p>For anything tagged informational, move it to a lower urgency tier with a slower escalation.</p>
</li>
<li><p>For actionable pages, check that the escalation timeout matches how much time the team actually has before impact grows.</p>
</li>
</ol>
<p>Most teams find that a third to half of their pages fall into noise or informational once they actually look, on the tool they already have. If fatigue is still there after that exercise, a new tool might genuinely help.</p>
<h2>FAQ</h2>
<p><strong>Does a better on-call tool ever fix alert fatigue?</strong> It can remove friction around fixing it, but the tool doesn't do the classification or ownership work for you.</p>
<p><strong>How do we know if our escalation policies are the problem?</strong> Check how many pages resolved themselves or were ignored until auto-resolve, versus how many required real action within the escalation window. A high self-resolving ratio usually means the timeout is too aggressive.</p>
<p><strong>Who should own alert hygiene without a dedicated SRE team?</strong> Rotate it with the on-call schedule: whoever was on-call last week reviews last week's pages before handing off.</p>
]]></content:encoded></item></channel></rss>