Daily alert digests now run per-site, isolated from each other

Daily alert digests were occasionally being missed because one slow site could swallow the whole anomaly-detector budget and starve every site after it. We've moved digest delivery to a per-site fan-out so each site's digest runs in its own isolated Lambda invocation.

The daily Alert Digest email summarises every qualifying anomaly across the previous 24 hours and lands at your configured digest_send_hour_utc (default 08:00 UTC). Behind the scenes that work was sharing a Lambda budget with the rest of the anomaly detector — and on busy days one noisy site (think: a wp-login brute force generating dozens of hacking_probe alerts in a single sweep) could consume the whole 5-minute budget by itself, leaving every site processed later in the iteration without a digest for the day.

The architecture is now per-site:

  • An hourly scheduler enumerates the sites due for a digest this hour and pushes one job per site onto an SQS queue.
  • A worker Lambda picks one job off the queue, sends that one site's digest, and stops.
  • Each site runs in its own invocation, fully isolated from every other site's workload — no shared time budget, no starvation.

Per-day idempotency markers still prevent any chance of a duplicate digest if a worker is retried, and the time-of-day window in your alert config still controls when delivery happens.

If you were missing digests over the last few days, today's send for sites with qualifying alerts has gone out. Past days' digests can't be recovered because the digest window is rolling 24h — the alerts those would have summarised are no longer in the window — but no live data was ever lost.

← Weekly report percentages are now correctAnomaly detection and storage rollups now run per-site too →
← All changelog entries