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

Database schema & key types

Four tables back the package:

TableColumnsNotes
health_checksid, notifiable_type + notifiable_id, health_check, frequency (nullable), max_attempts, decay_minutes, consecutive_failures, consecutive_successes, tags (json), meta (json), timestamps, deleted_atOne row per scheduled check per owner. A null frequency marks an on-demand row seeded by run() — the scheduler never queues it. Soft deletes.
alertsid, notifiable_type + notifiable_id, health_check_id, status, escalation_level, message (text), meta (json), triggered_at, recovered_at, open_slot, timestamps, deleted_atOne row per incident — recovered_at is null while it is open. open_slot is 1 while open and null once recovered; a unique (health_check_id, open_slot) index admits one open alert per check. Soft deletes; indexed on owner + health check.
alert_silencesid, key, notifiable_type + notifiable_id (nullable), reason, starts_at, ends_at, timestampsMute records: a check key, a tag or *, optionally scoped to one owner. Null starts_at means active immediately; null ends_at means until unmuted.
health_check_runsid, health_check_id, status, duration_ms, message (text), meta (json), ran_atOne immutable row per executed run, no timestamps. Indexed on health check + ran_at.

alerts and health_check_runs carry a foreign key onto health_checks that cascades on delete — which is why health_checks is published first. HealthCheck and Alert use soft deletes, so the cascade applies when a row is force-deleted.

Owner key type

Owners are polymorphic (notifiable_type + notifiable_id), so any Eloquent model can own health checks. key_type types the notifiable_id column on health_checks, alerts and alert_silences:

key_typeNotifiable columnsUse when your owners…
bigintmorphs() — unsignedBigInteger iduse Laravel’s default auto-incrementing keys (the default)
uuiduuidMorphs()use HasUuids
ulidulidMorphs()use HasUlids
# Set before you run the migrations — the notifiable columns are typed from it
ALERTS_KEY_TYPE=uuid

All your owner models must share one key type. The value is case-insensitive; an absent or blank key means bigint, and an unrecognized value throws InvalidConfigurationException when the migrations run instead of falling back. The package’s own tables always keep auto-incrementing ids.

Where options live

Per-monitor options that have no column — failAfter, recoverAfter, timeout, channel routing and the escalation policy — are stored inside the row’s meta json under reserved keys (see Scheduling checks), next to any meta of your own.

On-demand rows and open alerts

Running a check now for an owner that has no schedule for it seeds an on-demand row with a null frequency. It keeps that owner’s counters, history and alerts for the check between manual runs, but the scheduler never queues it (see Running checks). On alerts, the unique (health_check_id, open_slot) index guarantees at most one open alert per check, even when two failing runs overlap. Run and alert messages are text columns, stored up to 1000 characters.

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.