NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Alerts for Laravel

Maintenance windows & muting

Suppress alert notifications during deploys or maintenance while still recording runs. Health::silences() is the sub-accessor for maintenance windows:

use RoundlyConsulting\Alerts\Facades\Health;

Health::silences()->mute('disk_usage_check', until: now()->addMinutes(30), reason: 'db migration');
Health::silences()->isMuted('disk_usage_check');   // true
Health::silences()->unmute('disk_usage_check');    // int: silences lifted

Health::silences()->mute('critical');              // mute a whole tag
Health::silences()->mute('*');                     // mute everything
Health::silences()->mute('disk_usage_check', for: $team);   // scope the mute to one owner
Health::silences()->unmute('disk_usage_check', for: $team); // lift only that owner's silence
  • The key is a check key, a tag, or * for everything. At run time a row is muted when a mute matches its check key, any of its effective tags, or *.
  • until is optional: without it the mute holds until you unmute it. mute() starts immediately and returns the AlertSilence record, with an optional reason.
  • for: scopes the mute to one owner. A mute without an owner applies to everyone.
  • unmute() deletes the mutes for that key — the owner-scoped ones when you pass for:, otherwise only the global ones — and returns how many it lifted.
  • isMuted() checks for an active mute on exactly the key you pass — a check key, a tag or * — without expanding tags or *. Without an owner it matches any mute on that key; with one, that owner’s mutes plus the global ones. It returns false whenever silence is off in the config.

What happens while muted

Runs, history and counters are maintained, and alerts still open and close. HealthCheckFailed, HealthCheckRecovered, HealthCheckEscalated and every notification are suppressed. Touched alerts are flagged meta['muted'], so the status report shows them as muted. The flag follows the latest run, so it clears when failures continue after the window ends.

Set silence to false in the config to ignore every mute without deleting them.

Listing mutes

active() returns the silences in force now — all of them, or the global ones plus those scoped to an owner. For your own queries, AlertSilence has the active() and matching() scopes behind it:

use RoundlyConsulting\Alerts\AlertSilence;
use RoundlyConsulting\Alerts\Facades\Health;

Health::silences()->active();        // Collection<AlertSilence> in force now
Health::silences()->active($team);   // global silences + those scoped to $team

// The model scopes behind it, for your own queries:
AlertSilence::query()->active(now())->get();
AlertSilence::query()->matching(['critical'], $team)->exists();  // a 'critical' mute for this team, or a global one

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.