Skip to main content
Headway
Back to blog
Technology & innovation

How we cut appointment search latency by 70%

Rebuilding our provider-matching index around read replicas and precomputed availability windows made search feel instant — and instant search means more booked first appointments.
Marcus Lee & Devin ParkMay 28, 2026 · 8 min read
How we cut appointment search latency by 70%

When a patient searches for a therapist on Headway, they are not really searching a list of people — they are searching a list of open appointment times that match their insurance, their state, and the kind of care they need. That distinction is the whole reason search was slow, and fixing it is the whole reason it is now fast.

A year ago, a typical search took just under two seconds at the 95th percentile. For a product where the next step is booking an intake call, two seconds is enough hesitation to lose someone. We set a target of under 500 ms and ended up at roughly 540 ms p95 — a 70% reduction. Here is what actually moved the number.

Where the time was going

Our first instinct was that the database was the problem. It was — but not in the way we assumed. Profiling showed the query itself was fast; the cost was in computing availability on read. Every search joined providers against their calendars, expanded recurring rules into concrete slots, and filtered by payer — for every provider in the result set, on every request.1

Latency by request phase, before and after. Availability expansion dominated p95.
Latency by request phase, before and after. Availability expansion dominated p95.
Before: availability expanded per request.
Before: availability expanded per request.
After: precomputed slots read straight from the index.
After: precomputed slots read straight from the index.

Precomputing availability

Instead of expanding calendars at read time, we materialize the next 30 days of open slots per provider whenever their availability changes, and write the result straight into the search index. A booking, a cancellation, or a rule change enqueues a single recompute for that one provider.

// Recompute one provider's open slots on any availability change
const slots = await availability.materialize({
  providerId,
  window: { days: 30 },
});

await searchIndex.upsert(providerId, { slots });

Reads became a lookup instead of a computation. The index already knows who is open, when, and for which payers — so a search is now a filter over precomputed rows.

Search went from something patients endured to something that felt instant — and instant search means more booked first appointments.

Read replicas and a thinner index

Precomputation got us most of the way. The rest came from three smaller changes:

  • Routing all search reads to dedicated read replicas, so booking traffic never contends with browsing traffic.
  • Trimming the index to only the fields search actually filters and ranks on — specialty, modality, state, payer, and the slot windows.
  • Caching the payer eligibility lookup, which rarely changes within a session.
Note

We track search latency at p95, not average. Averages hide the slow searches, and the slow searches are exactly the ones where a patient gives up.

What changed for patients

Faster search is not the goal in itself. The goal is that someone who has worked up the nerve to look for a therapist finds one and books before the moment passes. Since the rollout, completed searches are up and the drop-off between search and first booking has narrowed measurably — which, for a mental-health platform, is the metric that matters.

What we measured

Completed searches, search-to-booking drop-off, and p95 latency — tracked per market so a regression in one state cannot hide behind the national average.


There is more to do — availability windows beyond 30 days, smarter ranking for first-time patients — but the architecture is finally one we can build on. If working on problems like this sounds good, we are hiring.

Footnotes

  1. We track the 95th-percentile latency rather than the average, because the slow tail is exactly where patients abandon a search.

Marcus Lee
Staff engineer, Search & Matching
Marcus works on the systems that connect patients to the right provider at the right time. Previously he built search infrastructure at two other health-tech companies.
Devin Park
Senior engineer, Billing & Claims
Devin builds the systems that turn a completed session into a paid claim, reliably, every time.

More from the blog