Back to blog
FILE 0x6F·MODERATE RISK ALERT AT MIDNIGHT, AWAKE AT THE DESK

Moderate risk alert at midnight, awake at the desk

May 18, 2026 · aws, lambda, alerts, anomaly-detection

A side-project safety app generated a moderate-severity risk alert for me at 00:28 local time. I was at my desk, awake, trading messages with two different people on Signal. The alert was false. Walking through why turned into a useful exercise in "what signals should trump what."

What was happening

The risk evaluator looks at recent activity inside the cron window. If activity is low and the time is outside the user's learned wake window, it flips the moderate risk factor on. At 00:28 I was past my median bed time, hadn't tapped the app in a while (most of my recent activity was elsewhere on the phone), and the cron correctly identified that as quiet from its perspective.

But "no activity inside the app" and "no activity at all" are not the same thing.

What I found

Three things compounded:

  1. The risk evaluator was scoring against the learned per-DOW wake window. That window placed my "should be active" bound somewhere around 00:00 — I'm a night owl, but only sometimes, and the median doesn't capture the variance.
  2. The app's activity table only sees events the app itself generates: app-foreground taps, location updates from the tracker, etc. Messaging traffic outside the app is invisible.
  3. There's no "you're home and demonstrably alive" suppressor for moderate alerts. The hard inactivity alert path has one (it tries an AI evaluator with full context); the moderate risk path doesn't.

The fix

The fix I wrote down was: "consider suppressing moderate alerts when location=home AND there's recent passive evidence of activity in the same timeframe." The trick is what counts as passive evidence if the user isn't using the app. Some candidates I considered:

For now the change I shipped was simpler: any GPS update within the last 15 minutes counts as a "passive heartbeat" for moderate-severity suppression at home. Doesn't help if the phone is sitting still on the desk, but covers the much more common case where the user is moving around the house. The risk evaluator now reads:

if ($severity <= RISK_MODERATE
    && $atHome
    && $minutesSinceLastFix < 15) {
    return null; // suppress
}

Hard inactivity and SOS paths are unaffected — those should still page through this kind of guard.

What I'd do differently

The deeper fix is to feed the AI evaluator into moderate alerts the same way it feeds hard alerts. The prompt would get in_sleep_window, at_home, minutes_since_last_fix, recent_signal_traffic_detected, etc., and decide whether to suppress. That's more work and more cost, and the simple heuristic above closes the specific case that fired.

The bigger lesson: don't infer "not alive" from "no events in the app." A safety system has to consider whatever signals the phone can provide as evidence of the user being okay, not just app events. If the user is moving their phone around, the system should know that without needing them to open the app.