Access Signals
Access Signals — Is the System Reaching People?
Access isn't just about enrollment numbers. It's about whether people can actually see a doctor when they need one. When they can't, they end up in the ER. When providers are stretched thin, quality suffers. This page tracks the warning signs.
Provenance
Methodological Guardrails
ER Reliance
When people use emergency rooms for care that a primary care doctor could handle, it usually means one thing: they couldn't get an appointment. ER visits cost 3-10x more, don't provide continuity, and signal a system that isn't meeting people where they are.
ER vs Primary Care Beneficiaries Over Time
View SQL (`er_data`)
SELECT * FROM medicaid.er_vs_primary_careER vs Primary Care Spending
ER Share of Combined Spending
ER-to-Primary-Care Beneficiary Ratio
A ratio above 1.0 means more people are visiting ERs than primary care offices in a given month. [Inference, Medium confidence] Even a ratio that stays flat while beneficiary touchpoints rise means the system isn't steering people toward lower-cost, higher-quality primary care.
Citation: er_data (source medicaid.er_vs_primary_care).
Provider Capacity
Provider counts alone don't tell the access story. What matters is whether there are enough providers relative to the people who need them.
Provider Count Over Time
View SQL (`attrition_filtered`)
SELECT * FROM medicaid.provider_attrition
WHERE category = '${inputs.capacity_category.value}'Beneficiaries per Provider
The Squeeze: Supply vs Demand
The most important access question: are we adding providers fast enough to keep up?
Growth Comparison: Jan 2018 to Oct 2024
View SQL (`growth_rates`)
WITH bookends AS (
SELECT
category,
month,
active_providers,
total_beneficiaries,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY month ASC) AS rn_first,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY month DESC) AS rn_last
FROM medicaid.provider_attrition
)
SELECT
f.category,
f.active_providers AS start_providers,
l.active_providers AS end_providers,
ROUND((l.active_providers - f.active_providers) * 100.0 / NULLIF(f.active_providers, 0), 1) AS provider_growth_pct,
f.total_beneficiaries AS start_beneficiaries,
l.total_beneficiaries AS end_beneficiaries,
ROUND((l.total_beneficiaries - f.total_beneficiaries) * 100.0 / NULLIF(f.total_beneficiaries, 0), 1) AS beneficiary_growth_pct,
ROUND((l.total_beneficiaries - f.total_beneficiaries) * 100.0 / NULLIF(f.total_beneficiaries, 0), 1)
- ROUND((l.active_providers - f.active_providers) * 100.0 / NULLIF(f.active_providers, 0), 1) AS gap
FROM bookends f
JOIN bookends l ON f.category = l.category AND l.rn_last = 1
WHERE f.rn_first = 1
ORDER BY gap DESCThe Gap column shows the difference between beneficiary growth and provider growth in percentage points. Positive values mean demand is outpacing supply. Every row with a positive gap represents a category where access is getting harder, not easier.
This is the fundamental tension in Medicaid: expanding coverage is necessary but not sufficient. Without investment in provider capacity, enrollment gains become paper coverage — people have a card but can't find a doctor who will see them.
Provider Attrition by Specialty
Which types of providers are leaving Medicaid — or entering it? By joining billing data to the NPI Registry's taxonomy codes, we can track active provider counts for specific specialties over time.
207Q00000X — Active Providers Over Time
View SQL (`top_specialties`)
SELECT
taxonomy_code,
SUM(paid_millions) AS total_paid_m
FROM medicaid.attrition_by_specialty
GROUP BY taxonomy_code
ORDER BY total_paid_m DESC
LIMIT 15Reproduce This Page
cd dashboard
export EVIDENCE_SOURCE__medicaid__token="<your_motherduck_token>"
export EVIDENCE_SOURCE__medicaid__database="medicaid"
npm run sources
npm run build
npm run preview
# then open http://localhost:3000/access
