Skip to content

Operational alerting has no receiver: SCALE_ALERT_WEBHOOK_URL unset, alerts terminate in-process #640

Description

@mkreyman

Operational alerting is implemented end to end but has no receiver, so every alert currently terminates in the process that raised it.

Current state (verified in prod, 2026-08-09)

  • SCALE_ALERT_WEBHOOK_URLnot set. fly secrets list holds only DATABASE_URL, CLOAK_KEY, SECRET_KEY_BASE, ECTO_IPV6, OPENAI_API_KEY, ANTHROPIC_API_KEY, TENANT_AUDIT_KEY_ECOMMERCE_FRIENDLY.
  • SCALE_ALERTS_ENABLED = "false" in fly.toml — deliberate, and the comment there says why: OFF means the ScaleAlerts child is not started at all, so no threshold is evaluated, logged or POSTed. Prometheus on METRICS_PORT remains the degradation signal.

This is a coherent, documented state, not a bug. The gap is that it has no follow-up attached, and the consequence is easy to misread.

Why it needs closing

alerted: true on an ingestion anomaly records that a ScaleAlertDeliveryWorker job was ENQUEUED, not that anyone was told. With no URL the worker logs scale_alert_webhook_url is unset at delivery time and skips. An operator reading the anomaly list sees five rows marked alerted and reasonably concludes someone was notified.

Concretely today: five capture_silence anomalies have carried alerted: true since mid-July (23 to 31 days) with no human aware of them. They turned out to be completed one-off imports rather than broken feeds, so nothing was lost this time. The next one will look identical.

The always-on Logger.error in IngestionHealthWorker still fires, so the information exists in the Fly logs. Nobody reads Fly logs on a cadence that would catch a month-old silence.

What to do

  1. Decide the receiver (Slack incoming webhook, PagerDuty, or a generic endpoint).
  2. Set BOTH halves in the same change: the SCALE_ALERT_WEBHOOK_URL secret AND SCALE_ALERTS_ENABLED = "true" in fly.toml. ScaleAlerts.config_status/2 flags either half-done direction and /health/ready goes red naming the setting to fix, so a one-sided change is caught rather than silently half-working.
  3. Confirm /health/ready returns 200 after the change (it is the deploy smoke gate and is deliberately not wired into fly.toml's continuous check, so it will not depool a node either way).

Optional, separate

Consider whether alerted should mean DELIVERED rather than ENQUEUED, or whether the field should be split. Not required to close this issue, and not worth doing until a receiver exists.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions