---
title: "Alarm fatigue"
description: "Escalation is budgeted rather than judged screen by screen. This page sets the ceiling, names who owns it, and says what an interface loses by overspending it."
url: "https://opsinjs.pensievelabs.org/health/alarm-fatigue"
source: "https://opsinjs.pensievelabs.org/health/alarm-fatigue.md"
section: "Health"
kind: "health"
evidence: "mixed"
reviewed: "2026-09-02"
reviewer: "design"
aliases: ["alert fatigue", "escalation budget", "too many alerts", "notification fatigue", "desensitisation"]
implements: ["alert-banner", "care-card", "status-pill"]
---

> Elements written as `<PascalCase … />` below are opsinjs documentation
> components. Their attributes are the content: the values they render are
> generated from `tokens/*.json` and `registry/catalogue.ts` and are
> published separately at https://opsinjs.pensievelabs.org/r/index.json and under the Reference
> section.
> Nothing is missing from this page. The data simply does not live in
> the prose.

<PageTemplate kind="health" />

## What this means [#what-this-means]

Alarm fatigue is the best-documented failure mode in clinical technology. In
hospitals, monitors generate enough alarms that competent, trained and motivated
staff stop responding to them, silence them pre-emptively, or tune them out
entirely. Each alarm is individually reasonable and the aggregate is noise, and
people have been harmed by alarms that fired correctly into a room where nobody
was listening any more. The evidence for alarm fatigue as a documented problem,
and the limits of its transfer to a consumer app, are set out under "Why
(evidence)" below.

Consumer health apps reproduce the pattern at lower stakes, until the stakes are
not low. A ring closes, a streak breaks, a weekly report is ready, a device needs
charging, a reading is a little high, a subscription is expiring, and each of
these arrives with the same visual weight and the same buzz. The reader learns
from the repetition that this app's notifications do not require action, and that
is the expectation they bring to the alert that does. How many low-value alerts
that learning takes is something we have not measured.

Each individual decision to escalate is defensible on its own terms, and fatigue
is a property of the aggregate rather than of any one decision. No single
screen's review can detect it, which is why opsinjs governs escalation with a
budget rather than with a per-screen judgement.

## The rule [#the-rule]

**Escalation is a finite, explicitly budgeted resource. Every surface that
escalates must be spent against a stated budget, and the budget is enforced
at the screen and at the session rather than at the component.**

### Escalation budgets by scope [#escalation-budgets-by-scope]

The budget sets five ceilings across four scopes, two of them at the screen.

| Scope       | Ceiling                                                         | Failure mode it prevents                                                                                                                                    | Basis                                                         |
| ----------- | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| One screen  | At most one `urgent` surface                                    | Two urgent surfaces on one screen ask the reader to decide which of them to act on first, and a lay reader has no basis on which to rank two urgent claims. | Follows from the triage argument; chosen rather than derived. |
| One screen  | At most two `attention` surfaces                                | Past two, the reader's scan is divided across the set, and we expect each surface to be read less closely than it would have been alone.                    | A judgement about scanning rather than a measurement.         |
| One session | At most one interruptive modal that the reader did not initiate | An interruption the reader did not ask for stops the task they opened the app to do, and it is the most expensive item in this budget.                      | A judgement about goodwill.                                   |
| One day     | At most one non-clinical push notification                      | A push arrives at a moment the reader did not choose, so a low-value one spends the attention that the next clinical one will need.                         |                                                               |
| Any surface | `urgent` is reserved for clinical urgency                       | A commercial or product problem rendered as `urgent` is indistinguishable from a clinical one at the moment the reader sees it.                             |                                                               |

Two of the five ceilings carry no entry under Basis. The daily limit on
non-clinical push is administered by
[Notifications and off-screen alerts](./notifications-and-off-screen-alerts.mdx),
which owns scheduling and grouping, and the reservation of `urgent` for clinical
urgency is fixed by the status vocabulary on
[Clinical status semantics](./clinical-status-semantics.mdx) rather than chosen
here.

### The escalation ladder [#the-escalation-ladder]

The ladder has five rungs in a normative order, and a surface moves up a rung
only when the rung below it has been used and has proved insufficient, never
because a rung looks more important.

| Rung            | Surface                                                                                        | Addressed to                                        | Blocks the reader                                            | Condition for using it                                                                                                                                                                                                                                |
| --------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1. Ambient      | A `StatusPill` on the value itself                                                             | Nobody in particular; it is a property of the value | No                                                           | The default rung, available wherever a status is shown                                                                                                                                                                                                |
| 2. In-place     | A `CareCard` in the flow of the screen, next to the value it is about, carrying a named action | The reader of that value, at the point it appears   | No                                                           | Rung 1 is in use and the value needs a named action travelling with it                                                                                                                                                                                |
| 3. Screen-level | An `AlertBanner` at the top of the screen                                                      | The reader of the screen                            | No                                                           | Rung 2 is in use and has proved insufficient                                                                                                                                                                                                          |
| 4. Interruptive | A modal or a sheet the reader must dismiss                                                     | The reader, at the moment they arrive               | Yes, until it is dismissed                                   | The message is time-critical and cannot wait for the reader to reach it                                                                                                                                                                               |
| 5. Off-screen   | A push notification                                                                            | The reader while the app is closed                  | It interrupts outside the app rather than blocking inside it | Rung 4 is in use and has proved insufficient, and the message is never a first attempt; it is the most expensive rung on the ladder, and its delivery is governed by [Notifications and off-screen alerts](./notifications-and-off-screen-alerts.mdx) |

### Rules that close the routes around the budget [#rules-that-close-the-routes-around-the-budget]

Every ceiling above can hold while escalation is still overspent, and three
further rules cover those cases: one fact carried on several rungs at once, a
surface that is never withdrawn, and a surface re-raised on a timer.

* **No parallel escalation.** The same fact does not get a pill and a card and a
  banner at once. One fact occupies the highest rung it justifies, and the
  surfaces below that rung are suppressed.
* **De-escalation and its announcement.** When a value returns to `steady`, the
  surface that escalated it is removed, and the reader is told once that it has
  gone.
* **The re-raise condition.** Repeating an unchanged `attention` banner on
  successive opens does not increase the chance of action, and it reduces the
  response rate to later banners. A surface re-raises on a change of state rather
  than on a timer.

<SafetyCallout severity="urgent" evidence="opinion">
  A value that may require emergency care outranks every ceiling on this page and
  suppresses all other alerts on the screen. That path is specified separately at
  [Emergency and escalation](./emergency-and-escalation.mdx), which owns its
  requirements, its surfaces and its acknowledgement behaviour.
</SafetyCallout>

## Why (evidence) [#why-evidence]

<ResearchNote evidence="mixed" date="2026-09-02">
  **Cited.** Alarm fatigue in clinical settings is a documented patient-safety
  problem rather than a designer's intuition. The Joint Commission has published
  a Sentinel Event Alert on medical device alarm safety in hospitals (Issue 50),
  and alarm-related hazards have appeared repeatedly in ECRI's annual health
  technology hazards lists. We name them so that a reader can look them up and
  read the current versions; we do not quote them, and we do not claim their
  findings transfer directly to a consumer phone app.

  **The transfer is our opinion.** Hospital alarms and app notifications differ
  in almost every respect except the mechanism we care about: repeated
  low-value signals from a source that is supposed to be trustworthy reduce
  response to high-value signals from that source. We consider that mechanism
  general across sources a person relies on, and we have not measured it in a
  consumer health product; we cite no study that has.

  **The numbers in the budget table are ours, and they were chosen rather than
  derived.** The Basis column above records the reasoning behind each of the
  three ceilings that has one. We publish them as numbers rather than as an
  instruction to use restraint, because a number can be reviewed, argued with and
  enforced, and an instruction to use restraint cannot.

  What would change our mind: any field data at all on consumer health alert
  response rates as a function of alert frequency. A dataset relating response
  rate to the number of concurrent `attention` surfaces would revise the
  two-per-screen ceiling, and a dataset relating response rate to un-requested
  interruptions per session would revise the one-per-session ceiling.
</ResearchNote>

## Applying it [#applying-it]

<DoDont>
  <DoDont.Do>
    Suppress the lower rungs when a higher one fires. If an `AlertBanner` is
    already telling the reader their blood pressure needs checking, the tile
    below shows a `watch` pill rather than a second banner.
  </DoDont.Do>

  <DoDont.Dont>
    Let every component decide its own urgency independently. No component-level
    review sees the aggregate of the screen, so a set of individually reasonable
    decisions produces an unreadable screen that passes every one of those
    reviews, which is why enforcement sits at the screen and at the session.
  </DoDont.Dont>
</DoDont>

<DoDont>
  <DoDont.Do>
    Track alert volume per user as a product metric with a target ceiling, the
    way you track error rate. A stated ceiling is what makes the aggregate
    reviewable after release, where a screen-level review cannot reach.
  </DoDont.Do>

  <DoDont.Dont>
    Measure alerts by click-through alone. Click-through on a newly introduced
    alert measures its novelty as much as its value, and it does not show what
    happens to the response rate as the same alert repeats unchanged.
  </DoDont.Dont>
</DoDont>

<DoDont>
  <DoDont.Do>
    Tell the reader when something has resolved: "Your blood pressure readings
    are back in your usual range." The sentence states both that the surface has
    gone and why it has gone, and the de-escalation rule above requires it to be
    said once rather than repeated.
  </DoDont.Do>

  <DoDont.Dont>
    Remove the banner without saying anything. A reader who cannot tell whether
    the value returned to `steady` or the app dropped the surface has no reason
    to treat the next banner as reliable.
  </DoDont.Dont>
</DoDont>

<DoDont>
  <DoDont.Do>
    Give engagement, retention and commercial messages their own quiet channel
    that is visually and structurally separate from the clinical one, so that a
    reader can tell which channel a message arrived on before reading it.
  </DoDont.Do>

  <DoDont.Dont>
    Borrow the clinical channel for a streak reminder because it gets noticed.
    The attention it borrows is the attention the next clinical alert on that
    channel will need, and the reader has no way to tell the two apart in
    advance.
  </DoDont.Dont>
</DoDont>

Sound and haptics carry their own budget, and it is smaller than the visual one
because a sound or a vibration cannot be skimmed past and reaches whoever is
nearby as well as the reader. See
[Sound and haptics](../foundations/sound-and-haptics.mdx) and
[Motion in health UI](./motion-in-health-ui.mdx).

## Components that implement this [#components-that-implement-this]

{/* Generated from `implements`. Do not restate the list by hand. */}

`AlertBanner` is specified to expose the budget rather than hide it: a screen
that mounts a second `urgent` banner should fail loudly in development instead of
rendering two. That behaviour is a specification and not shipped code. The
component itself ships and does warn in development about several
things, including a missing heading level and an `attention` or `urgent` banner
with no action, but nothing counts banners across a screen, because a component
cannot see its siblings. The budget is enforced by review today, and the
specified behaviour is what the component will be held to when something can
enforce it.

## What this does not cover [#what-this-does-not-cover]

Four topics fall outside this page. Three of them are covered elsewhere in the
corpus, and continuous clinical monitoring is outside opsinjs altogether.

| Excluded topic                                             | Why it is out of scope                                                                                                                 | Where it is covered                                                              |
| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| Which readings deserve to escalate at all                  | The decision is a clinical threshold, and opsinjs does not set clinical thresholds                                                     | [Clinical status semantics](./clinical-status-semantics.mdx)                     |
| Notification scheduling, quiet hours and OS-level grouping | Delivery mechanics are governed separately from the ceilings this page sets                                                            | [Notifications and off-screen alerts](./notifications-and-off-screen-alerts.mdx) |
| The interaction pattern for staged escalation              | This page fixes the ceilings and the ladder, while the sequence, the wording and the components belong to a pattern                    | [Alert escalation](../patterns/alert-escalation.mdx)                             |
| Clinical monitoring systems                                | Continuous monitoring with alarms is a regulated domain with its own standards, and it requires an analysis this page does not attempt |                                                                                  |

## Updates to this page [#updates-to-this-page]

<Reviewed />
