Home / Tools / Drugs and formularies
formulary_churn
Formulary Churn
What it answers
Given a quarter-pair (report_quarter_from, report_quarter_to) AND a formulary or plan filter, returns the formulary delta: drugs added, drugs dropped, drugs re-tiered, and optionally drugs whose control flags (prior auth / step therapy / quantity limit) changed. Diffs drug_silver.fact_drug_formulary across two SPUF report_quarters on (formulary_id, ndc11) keys.
Returns: per-category row lists (cap 5000 each), aggregates (formularies_compared, n_added, n_dropped, n_tier_changed, n_control_changed, n_unchanged, churn_rate, tier_movement_distribution), truncated_by_category flags.
READING churn_rate: it is (added + dropped + re-tiered) divided by the number of drugs on the formulary in the FROM quarter — CHANGE EVENTS PER FROM-QUARTER DRUG, not a percentage. It is >= 0 and CAN EXCEED 1 (a formulary that drops everything and adds as many new drugs scores 2.0), because added drugs are not members of the denominator. The answer carries churn_rate_definition saying exactly this, the two denominators (n_in_from_quarter, n_in_to_quarter), and two bounded companions that ARE 0-1: share_dropped (dropped / FROM-quarter drugs) and share_added (added / TO-quarter drugs).
Use cases: year-over-year formulary stability tracking, drop investigations for a specific drug class, IRA-era churn rate (crossing 2025 → 2026 will surface the redesign-driven churn).
KNOWN GAPS: spuf_quarterly_publication_lag (CMS publishes 6 weeks after quarter end; very recent quarter changes won't show); ira_era_break_2026 (IRA Part D redesign in 2026 changed formulary structures; churn comparison crossing this boundary mixes regime changes with normal churn); formulary_churn_truncated (per-category lists capped at 5000).
Inputs
report_quarter_fromreport_quarter_toacknowledge_era_breakcontract_id_filterformulary_id_filterinclude_control_changesplan_id_filterCall it
From an agent: connect the Vlada MCP once (one click for Claude, ChatGPT, Cursor, VS Code) and ask in plain English; the agent selects formulary_churn when the question fits. From code: the same tool over REST with an API key. The schema endpoint needs no key.
curl -X POST https://api.vladahealth.com/v1/tools/formulary_churn \
-H "Authorization: Bearer $VLADA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"report_quarter_from":"<report_quarter_from>","report_quarter_to":"<report_quarter_to>"}'curl https://api.vladahealth.com/v1/tools/formulary_churn/schema # the JSON schema, no auth # MCP endpoint (Streamable HTTP): https://mcp.vladahealth.com/mcp
What comes back
Typed rows plus provenance on every answer: the public source file, its vintage, the methodology, and a response_hash you can replay. Prove and replay tools turn any number into a re-runnable receipt. A number the data cannot support comes back as “not in the data”, never as zero.
Sources behind it
- drug_silver.fact_drug_formulary
- drug_silver.dim_part_d_plan
tables: drug_silver.fact_drug_formulary · drug_silver.dim_part_d_plan
Known limits
- spuf_quarterly_publication_lag
- ira_era_break_2026
- formulary_churn_truncated
- formulary_churn_no_match
As of the 2026-09-19 build of the served surface · machine-readable catalog · the live server may run a different version; the schema endpoint above is authoritative for what is deployed.