Cloudflare.Alerting reference
CustomAlert
Section titled “CustomAlert”Source:
packages/cloudflare/src/Alerting/CustomAlert.ts
A Cloudflare custom alert: a SQL query Cloudflare runs on a schedule, with a trigger that decides when to notify.
The query runs against the
SQL API, so it
can read Workers logs and traces, HTTP requests, Analytics Engine
datasets and the other analytics datasets. Notifications go to the same
destinations as a NotificationPolicy (email, webhooks, PagerDuty).
CustomAlert: Alerting on a threshold
Section titled “CustomAlert: Alerting on a threshold”yield* Cloudflare.Alerting.CustomAlert("ErrorSpike", { query: `SELECT count() AS value FROM logs.workersLogs WHERE accountTag = '${accountId}' AND level = 'error'`, trigger: { type: "threshold", operator: ">", value: 100, window: "5m" }, every: "5m", mechanisms: { email: [{ id: "ops@example.com" }] },});CustomAlert: Alerting on anomalies
Section titled “CustomAlert: Alerting on anomalies”yield* Cloudflare.Alerting.CustomAlert("TrafficAnomaly", { query: `SELECT count() AS value FROM events.httpRequests WHERE accountTag = '${accountId}'`, trigger: { type: "anomaly", direction: "both", zScore: 3, window: "5m", baselineWindow: "1h", }, mechanisms: { webhooks: [{ id: webhook.webhookId }] },});CustomAlert: Alerting on an SLO
Section titled “CustomAlert: Alerting on an SLO”yield* Cloudflare.Alerting.CustomAlert("Availability", { query: `SELECT 100 * countIf(httpStatus < 500) / count() AS value FROM logs.workersLogs WHERE accountTag = '${accountId}'`, trigger: { type: "slo", target: 99.9, shortWindow: "5m", longWindow: "1h" }, mechanisms: { pagerduty: [{ id: pagerDutyId }] },});consumeNotifications
Section titled “consumeNotifications”Source:
packages/cloudflare/src/Alerting/NotificationEventSource.ts
Run an Effect for every notification a policy fires.
Call it in the Construction phase of any runtime that receives HTTP (a
WebhookHost, such as a Cloudflare Worker). Cloudflare then delivers the
policy’s notifications to that runtime: the event source creates a webhook
destination at the runtime’s URL and adds it to the policy, so the policy
needs no mechanisms of its own.
consumeNotifications: Examples
Section titled “consumeNotifications: Examples”Open a GitHub issue for each new Worker issue
const policy = yield* Cloudflare.Alerting.NotificationPolicy("IssuePolicy", { alertType: "workers_observability_real_time_issue",});
// `text` is Cloudflare's report: a summary line, then details and links.const createIssue = yield* GitHub.CreateIssue(yield* Repo);yield* Cloudflare.Alerting.consumeNotifications(policy, (notification) => createIssue({ title: notification.text.split("\n")[0], body: notification.text, }),);Page on a SQL custom alert, with your own secret
const errors = yield* ErrorSpike; // a Cloudflare.Alerting.CustomAlert
yield* Cloudflare.Alerting.consumeNotifications( errors, { secret: yield* Config.Redacted("ALERT_WEBHOOK_SECRET") }, (notification) => notification.alertEvent === "ALERT_STATE_EVENT_END" ? pager.resolve(notification.alertCorrelationId) : pager.trigger(notification.alertCorrelationId, notification.text),);NotificationEventSourceLive
Section titled “NotificationEventSourceLive”Source:
packages/cloudflare/src/Alerting/NotificationEventSourceLive.tsKind: Layer · Provides:Cloudflare.Alerting.NotificationEventSource
Cloudflare.Alerting.consumeNotifications on any WebhookHost.
Deploy-time: creates a NotificationWebhook destination pointing at
the host (at a per-policy path) and binds it onto the policy, so the policy
notifies the host. The webhook secret (yours, or a generated one) is bound
onto the host. Under alchemy dev the host is on localhost, which
Cloudflare can’t reach, so no destination is created.
Runtime: claims requests on the policy’s path, rejects any without the
secret in cf-webhook-auth, acknowledges Cloudflare’s test message, and
runs the handler once per notification.
NotificationPolicy
Section titled “NotificationPolicy”Source:
packages/cloudflare/src/Alerting/NotificationPolicy.ts
A Cloudflare Notifications policy.
A notification policy connects an alert type (the event Cloudflare watches for) to one or more destinations — email addresses, webhook destinations, or PagerDuty services — optionally narrowed by filters.
NotificationPolicy: Creating a policy
Section titled “NotificationPolicy: Creating a policy”Email notifications for Universal SSL events
yield* Cloudflare.Alerting.NotificationPolicy("SslAlerts", { alertType: "universal_ssl_event_type", mechanisms: { email: [{ id: "ops@example.com" }] },});Disabled policy with a description
yield* Cloudflare.Alerting.NotificationPolicy("SslAlerts", { alertType: "universal_ssl_event_type", enabled: false, description: "Paused during migration", mechanisms: { email: [{ id: "ops@example.com" }] },});NotificationPolicy: Webhook destinations
Section titled “NotificationPolicy: Webhook destinations”const webhook = yield* Cloudflare.Alerting.NotificationWebhook("AlertsHook", { url: "https://alerts.example.com/cf",});
yield* Cloudflare.Alerting.NotificationPolicy("SslAlerts", { alertType: "universal_ssl_event_type", mechanisms: { webhooks: [{ id: webhook.webhookId }] },});NotificationPolicy: Filters
Section titled “NotificationPolicy: Filters”yield* Cloudflare.Alerting.NotificationPolicy("HealthAlerts", { alertType: "health_check_status_notification", mechanisms: { email: [{ id: "ops@example.com" }] }, filters: { healthCheckId: [healthCheckId], newHealth: ["Unhealthy"], },});NotificationPolicy: Handling notifications in code
Section titled “NotificationPolicy: Handling notifications in code”consumeNotifications adds a webhook destination at the consuming
runtime, so the policy needs no mechanisms.
const policy = yield* Cloudflare.Alerting.NotificationPolicy("SslAlerts", { alertType: "universal_ssl_event_type",});
// in a Worker's Construction phase, with NotificationEventSourceLive providedyield* Cloudflare.Alerting.consumeNotifications(policy, (notification) => Effect.log(notification.text),);Alerts on a SQL query (Cloudflare’s custom_analytics alert type) have
their own resource with typed triggers: Cloudflare.Alerting.CustomAlert.
NotificationPolicy: Workers Issues notifications
Section titled “NotificationPolicy: Workers Issues notifications”const policy = yield* Cloudflare.Alerting.NotificationPolicy("IssuePolicy", { alertType: "workers_observability_real_time_issue", mechanisms: { email: [{ id: "ops@example.com" }] },});
yield* Cloudflare.Workers.IssueAutomation("IssueAlerts", { policyId: policy.policyId, afterOccurrences: 5,});Silence
Section titled “Silence”Source:
packages/cloudflare/src/Alerting/Silence.ts
A Cloudflare Notifications silence window.
A silence suppresses notification dispatches for a
NotificationPolicy between startTime and endTime — e.g.
during a planned maintenance window. The window times are explicit
ISO8601 props supplied by you; Cloudflare requires the start time to be
within 90 days of now.
Note: the create API returns no id, so the provider resolves the created
silence by listing and matching on (policyId, startTime, endTime). Two
silences sharing the exact same policy and window are indistinguishable.
Silence: Creating a silence
Section titled “Silence: Creating a silence”const policy = yield* Cloudflare.Alerting.NotificationPolicy("SslAlerts", { alertType: "universal_ssl_event_type", mechanisms: { email: [{ id: "ops@example.com" }] },});
yield* Cloudflare.Alerting.Silence("MaintenanceWindow", { policyId: policy.policyId, startTime: "2026-07-01T00:00:00Z", endTime: "2026-07-01T04:00:00Z",});Silence: Updating the window
Section titled “Silence: Updating the window”Window times are mutable — changing them updates the existing silence.
yield* Cloudflare.Alerting.Silence("MaintenanceWindow", { policyId: policy.policyId, startTime: "2026-07-01T00:00:00Z", endTime: "2026-07-01T08:00:00Z",});NotificationWebhook
Section titled “NotificationWebhook”Source:
packages/cloudflare/src/Alerting/Webhook.ts
A Cloudflare Notifications webhook destination.
Webhook destinations receive alert notifications dispatched by notification policies. Cloudflare sends a test POST to the URL when the webhook is created or updated, so the endpoint must be live and respond with a 2xx.
NotificationWebhook: Creating a Webhook destination
Section titled “NotificationWebhook: Creating a Webhook destination”Generic webhook with a generated name
const webhook = yield* Cloudflare.Alerting.NotificationWebhook("AlertsHook", { url: "https://alerts.example.com/cf",});Webhook with an auth secret
The secret is sent in the cf-webhook-auth header on every dispatch.
const webhook = yield* Cloudflare.Alerting.NotificationWebhook("AlertsHook", { name: "production-alerts", url: "https://alerts.example.com/cf", secret: yield* Config.Redacted("WEBHOOK_SECRET"),});NotificationWebhook: Using with a Notification policy
Section titled “NotificationWebhook: Using with a Notification policy”yield* Cloudflare.Alerting.NotificationPolicy("SslAlerts", { alertType: "universal_ssl_event_type", mechanisms: { webhooks: [{ id: webhook.webhookId }] },});NotificationWebhook: Looking up an existing webhook
Section titled “NotificationWebhook: Looking up an existing webhook”NotificationWebhook.lookup references a destination Alchemy doesn’t
manage (created in the dashboard or by another stack), found by
webhookId or name. It is read during plan/deploy and never created,
updated or deleted.
const pager = Cloudflare.Alerting.NotificationWebhook.lookup({ name: "pager" });yield* Cloudflare.Alerting.NotificationPolicy("SslAlerts", { alertType: "universal_ssl_event_type", mechanisms: { webhooks: [{ id: pager.webhookId }] },});