DEV Community

Vishal Kumar
Vishal Kumar

Posted on

Building a Durable 30-Day Outreach Cadence (Harder Than It Sounds)

The setup

Post-discharge follow-up reduces hospital readmissions — this is settled, and Medicare reimburses it through Transitional Care Management codes. Yet fewer than 10% of eligible beneficiaries received TCM after discharge (9.3%, per 2016 figures). Meanwhile about 75% of hospitals in the CMS readmissions program are paying penalties this year.

It's not a belief problem. Somebody has to contact thousands of people on a schedule and pay attention to the answers, and nobody has the staff. That's a throughput problem, which makes it an interesting systems problem.

Here's what building the outreach cadence actually involves. It looks trivial until you write it.

Why "just schedule some messages" fails

The naive version is a cron job that fires messages at day 2, 7, 14, 25. It breaks immediately:

  • The schedule is per-patient, not global. Day 2 is relative to that discharge. You're not running one schedule, you're running N concurrent stateful schedules that each started at a different wall-clock time.
  • Patients reply whenever. A reply to the day-7 message may land on day 9. Your state machine has to accept out-of-order input and still know where it is.
  • A reply can change the whole plan. "I'm short of breath" should abandon the remaining cadence and escalate. A branch mid-sequence, not at the start.
  • Non-response is a signal, not an absence. Silence needs retry, then escalation to human outreach. Doing nothing is the one wrong answer.
  • It has to survive a deploy. These sequences run for 30 days. Any in-memory state is gone the first time you ship on a Tuesday.

That last one is the real constraint and it drives everything else.

Durable state, not in-process timers

The whole thing has to be Postgres-authoritative. Each patient's sequence is a row with its position, next-action timestamp, and accumulated responses. A scheduler wakes up, queries what's due, and acts. setTimeout and in-memory queues are disqualified — not because they're inelegant but because a 30-day workflow will outlive dozens of restarts.

The corollary is that every step must be idempotent. Your scheduler will occasionally process the same due item twice (crash between action and state-write, at-least-once delivery, retries). Sending a heart failure patient the same check-in twice is a bad experience; escalating them to a nurse twice is worse. Every action needs a natural dedupe key and a check before it fires.

Response triage is a routing problem, not an NLP problem

It's tempting to treat inbound replies as a language-understanding challenge. Mostly they aren't. The structure that works:

  1. Ask closed questions. "Has your weight gone up more than 3 pounds since you got home? Yes/No" is answerable by SMS and by a state machine. Open-ended "how are you feeling?" produces text nobody can route.
  2. Classify against a clinician-defined rubric, not a general-purpose sentiment model. The thresholds are a clinical governance decision and belong to the health system — you're implementing their rule, not inventing one.
  3. Escalate with the whole context attached. A nurse getting "patient reports swelling" and having to go look everything up is barely better than nothing. The escalation should carry the answers, the trend across prior check-ins, and the discharge summary.
  4. Fail toward the human. Anything the classifier is unsure about goes to a person. The asymmetry is obvious: an unnecessary nurse review costs minutes, a missed decompensation costs an admission.

The scheduling primitives you end up needing

Working through this, the cadence engine needs roughly:

  • Per-entity schedules with relative anchors (t+2d from a discharge event, not a fixed date)
  • Branch — a response routes to a different subsequent path
  • Skip — a completed follow-up appointment cancels the remaining appointment-nagging steps
  • Fan-in — several signals (no response + missed appointment) combine into one escalation rather than three
  • Cancellation — readmission or death must halt the sequence immediately, and yes, you have to handle that case explicitly and carefully

If that list looks like a workflow DAG, it is. We ended up building it as one in our routines engine rather than as a message scheduler, because "sequence of timed sends" is the wrong abstraction the moment responses can alter the path.

What the agent can't do

Worth stating plainly since this is care delivery: an agent cannot deliver or bill TCM. That requires a provider's face-to-face visit. What it does is extend reach — more eligible patients enter a follow-up pathway at all, and concerning cases reach a clinician sooner. The outcome research on TCM describes human-delivered care, and I'm not claiming an automated cadence reproduces it.

We build this pattern at IntelliBooks Studio. Happy to get into the idempotency keys or the DAG state model in the comments.

Top comments (0)