Inspiration

I'm a pre-med engineering student, and I kept coming back to one place where the people most likely to decline quietly get the fewest eyes at night: nursing homes.

  • Overnight, state staffing rules allow one caregiver for 15 or more residents (e.g. Maine 1:15, Connecticut 1:16), on rounds every two hours.
  • About half of nursing-home residents fall every year, about twice the rate of older adults at home (AHRQ PSNet).
  • In the elderly, an infection heading toward sepsis often shows up as confusion and restlessness, not a fever, so fixed alarms miss it, or ring all night until staff tune them out.

People decline between rounds. I wanted a tool that tells one tired aide who to check next, and why.

What it does

Vigil monitors every resident around the clock from a wristband and an under-mattress bed sensor, learns each resident's own normal, and gives the night shift one calm, ranked list.

  • Rounds Queue: a "Check next" card in plain language ("Breathing faster and heart rate higher than usual for her, and restless in bed since about 11 pm"), bedside checks, and a big "I checked on Rosa" button. A hallway floor plan shows every room.
  • Two speeds:
    • Fast tier (Tiger Data, seconds): falls, extreme vitals, a resident who has stopped moving, a high-fall-risk resident out of bed alone at night.
    • Deep tier (Snowflake, minutes): quiet drift judged against each person's own history, forecasts, and AI that reads their care plan.
  • Resident page: why now → what to check at the bedside → verbatim care-plan quotes → who to call, based on code status (full code vs. comfort care). The detailed charts, NEWS2 and the score breakdown are one tap away.
  • Nurse notes by voice: "She seems more confused tonight and barely drank" → transcribed and structured → new confusion adds 3 NEWS2 points.
  • Shift handoff in SBAR format, and "Ask the facility" questions in plain English for the Director of Nursing.
  • Replay of last night through the full pipeline, and a live demo with real hardware: I'm resident 120, my Polar band streams my heart rate over Web Bluetooth, and my iPhone under the pillow is the bed sensor. When I get out of bed alone at night, I'm #1 and Critical within seconds.

On the scripted night, fixed thresholds fired 903 alarms; Vigil raised 22. It flagged Rosa, an 87-year-old with a silent UTI drift, 1 h 18 min before her scheduled round and 3 h 20 min before the first fixed alarm.

How we built it

Two integrations, two jobs: Tiger Data is the live layer ("what is happening now"); Snowflake is the intelligence layer ("what it means, and what to do").

Tiger Data (TimescaleDB on Tiger Cloud): the live layer

  • Hypertables for every sensor reading (33.7 M rows: 120 simulated residents every 5 s, plus my live Polar band and iPhone at 1 s) and for events.
  • Hierarchical continuous aggregates 1 min → 15 min → 1 h with real-time aggregation. A 7-day hourly query for all residents runs ~43× faster than raw.
  • Columnstore compression: 14.8× (4.0 GB → 274 MB).
  • Hyperfunctions: time_bucket_gapfill + locf for charts, percentile_agg/approx_percentile for each resident's personal baseline by time of day, heartbeat_agg for device liveness, state_agg for time in bed, and an add_job hourly baseline job.
  • The fast-tier evaluator scores all 120 residents every 2 s straight from Tiger (NEWS2, fall and bed-exit rules, hysteresis, alarm-fatigue suppression).

Snowflake: the intelligence layer (through its REST APIs: SQL API, Cortex Search REST, Cortex Analyst REST)

  • SNOWFLAKE.ML.ANOMALY_DETECTION: 5 multi-series models (HR, RR, SpO₂, skin temp, night restlessness), one series per resident, so each person is judged against their own normal (255k results).
  • SNOWFLAKE.ML.FORECAST: predicts when breathing will cross a NEWS2 danger threshold, before it happens.
  • Cortex COMPLETE (Claude) + Cortex Search: 120 synthetic care-plan PDFs → AI_PARSE_DOCUMENT → 1,200 chunks → a search service. Claude writes bedside checks that quote the care plan verbatim, with a wording guard (decision support, never a diagnosis).
  • AI_TRANSCRIBE + AI_EXTRACT: voice and typed nurse notes become structured findings.
  • AI_AGG: the SBAR shift handoff. Cortex Analyst: plain-English questions → SQL over a semantic model.
  • Every Snowflake call is counted and shown on an "Under the hood" page.

App: FastAPI (Python) + Next.js/TypeScript behind Caddy. A seeded physiology simulator for 120 residents with a scripted "last night". Web Bluetooth for the Polar Verity Sense, and DeviceMotion for the iPhone bed sensor. A calm night/day UI in Atkinson Hyperlegible, designed to be read at arm's length on a tablet.

Challenges we ran into

  • Making silent decline actually silent. The first version of the story escalated on a "more confused" note at 21:30, which gave everything away. I redesigned the scenario so Snowflake's anomaly models catch the drift before any human documents confusion; the confusion is discovered because Vigil sent the aide.
  • Teaching the models night vs. day. Two days of history wasn't enough, and whole-day movement bands were too wide to see restlessness. The fix was 9 days of training and a night-in-bed-only movement model.
  • Trial-account limits: Cortex's inference:complete REST endpoint returned 403, so Claude runs through the SQL REST API instead. Parallel anomaly detection also saturated the warehouse; I capped concurrency and cancel queries on shutdown.
  • Real hardware: turning an iPhone under a pillow into a reliable bed-exit sensor (tilt detection plus calibration), without false alarms when someone rolls over.

Accomplishments that we're proud of

  • On the same night: 903 fixed-threshold alarms vs. 22 Vigil alerts, and Rosa flagged hours earlier.
  • A COPD resident who would trigger 18 fixed alarms gets zero, because Vigil judges her against her own normal.
  • A live, real-hardware demo: out of bed → Critical in ~6 seconds, with the care plan's fall precautions already on screen.
  • Every number on the proof page is a live query, not a slide.

What we learned

  • In geriatrics, "abnormal" has to mean abnormal for this person. Personal baselines beat fixed thresholds on both sensitivity and alarm fatigue.
  • Splitting "now" (Tiger) from "what it means" (Snowflake) made the system faster and more robust: emergencies never wait on ML, and if Snowflake is slow, the fast tier keeps working.
  • Wording matters clinically: decision support, bedside checks and code status, never a diagnosis.

What's next for Vigil

  • A pilot with real devices in a skilled nursing facility, and a clinical review of the thresholds with nurses.
  • Learning from nurse feedback ("checked: she was fine") to tune each resident's sensitivity.
  • A family view, EHR integration, and a HIPAA-ready deployment.

All data is synthetic. No cameras. Decision support, not a diagnosis.

Built With

Share this project:

Updates

Submission history