Revenue Cycle Performance Report

A revenue-cycle dashboard for a hospital-system-owned ambulatory practice, for a Quality/PI and finance committee: clean claim rate and denial rate (by claim count and by dollars), a denial-reason breakdown, a payer-mix comparison, and net collection rate trended monthly.

Synthea does not model claim adjudication, so every denial outcome, denial reason, and collection figure on this page is synthesized - see the scope panel below before citing any number.

About this report

Claims are built one-per-encounter from encounter_class IN ('ambulatory', 'wellness') rows of a Synthea CSV export (https://github.com/synthetichealth/synthea). Billed amount and allowed amount come straight from the encounter's cost fields; everything about whether a claim was denied, why, and how much was collected is this project's own synthetic model, tunable from Edit Settings.

Data covers service dates from 2025-09 through 2026-08.

What is real and what is synthetic — read this before citing any number below

"Allowed amount" is Synthea's PAYER_COVERAGE field, relabeled. Synthea computes it as its own internal cost-sharing figure; this report repurposes it as a stand-in for a payer's contracted allowed amount. It is not a real payer-contract lookup, and Synthea gives no clean split between contractual write-off and patient responsibility.

Denial occurrence, denial reason, and collection rates are entirely synthetic. Synthea models charge/payment/transfer flows but has no concept of a payer denial, a CARC reason code, an appeal, or an adjudication outcome. This report does not read Synthea's claims_transactions.csv; it assigns each claim a clean/ denied status from an author-chosen base denial rate per payer category (not sourced from MGMA/HFMA or any real benchmark) and models collections from that. The base rates and every other knob are on the Edit Settings page.

Self-pay / uninsured encounters are excluded from claims entirely - there is no third-party adjudication to model for them.

92.5%
Clean claim rate (target 95.0%)
7.5%
Denial rate by claim count (680 of 9061)
6.0%
Denial rate by billed dollars
92.3%
Net collection rate (target 96.0%)

Denials

Clean claim rate is the share of claims accepted on first submission. The denial rate is shown both ways because a payer that denies many small claims and one that denies a few large ones are different problems.

Denial reasons (denied claims only)

ReasonDenied claimsShare of denialsDenied billed $$ share
Missing/incomplete information 183 26.9% $100,740.36 25.5%
Missing prior authorization 154 22.6% $97,755.07 24.7%
Diagnosis/procedure code mismatch 129 19.0% $78,649.51 19.9%
Not deemed medically necessary 109 16.0% $70,998.95 18.0%
Timely filing limit exceeded 105 15.4% $47,042.92 11.9%

By payer category

Payer-mix-driven denial variance is a real PI-committee conversation - here the drivers are the author-chosen base rates, not observed payer behavior. The Medicaid row includes Dual Eligible.

Payer categoryClaimsDenial rateNet collection rate
Medicare 6262 6.1% 92.6%
Medicaid 1157 13.1% 91.5%
Commercial 1642 8.9% 92.9%

Collections

Net collection rate is actual dollars collected ÷ allowed amount (expected reimbursement) over the period - a truer profitability signal than gross charges. Claims with an allowed amount of $0 (full patient responsibility / deductible) are excluded from this denominator.

Retroactive adjustment impact

The model applies a small per-claim chance of a later downward adjustment (recoupment) to clean claims - fabricated variance, no claim to represent real payer recoupment patterns. Without it, net collection rate would have been 93.4%; the adjustments (319 claims, $45,984.24) drag it down 1.0 pts to the headline 92.3%.

Patient responsibility

3158 claims (34.9% of claims, 18.3% of billed dollars) have a high modeled patient-responsibility share. This is tracked alongside the denial rate, not counted in it - a patient balance is not a payer denial.

Month-over-month variance callouts

Rule-based flags only: a swing is listed when it clears a configured threshold (Edit Settings). This reports the size and direction of a change - it does not attempt to explain the cause.

MonthMetricChangen
2026-07 → 2026-08 Denial rate Denial rate rose +5.6 pts 69
2026-07 → 2026-08 Net collection rate Net collection rate fell -4.9 pts 69
2026-07 → 2026-08 Claim volume Claim volume fell -41% 69
2026-05 → 2026-06 Denial rate Denial rate fell -3.9 pts 123
2026-05 → 2026-06 Net collection rate Net collection rate rose +4.7 pts 123
2026-04 → 2026-05 Net collection rate Net collection rate fell -8.2 pts 113
2026-02 → 2026-03 Denial rate Denial rate fell -3.3 pts 120
2026-01 → 2026-02 Claim volume Claim volume fell -23% 112
2025-12 → 2026-01 Denial rate Denial rate rose +4.3 pts 145
2025-10 → 2025-11 Net collection rate Net collection rate rose +5.3 pts 113
2025-10 → 2025-11 Claim volume Claim volume fell -20% 113
2025-09 → 2025-10 Denial rate Denial rate fell -3.3 pts 142

Metric definitions

Clean claim rate
Share of claims with claim_status = 'clean' - accepted on first submission, no denial assigned by the synthetic model.
Denial rate
Share of claims denied, by claim count and (separately) by billed dollars. Entirely synthetic - driven by the per-payer-category base rates on the Settings page.
Allowed amount ("expected reimbursement")
Synthea's PAYER_COVERAGE, relabeled - a single modeled figure, not a payer-contract lookup. Synthea does not split contractual adjustment from patient responsibility.
Net collection rate
Actual dollars collected ÷ allowed amount over the period - the "truer profitability signal than gross charges" measure. Excludes claims whose allowed amount is $0.
Denial reason (CARC-style)
One of five fabricated categories assigned to a denied claim. PR-1 (patient deductible/coinsurance) is deliberately not among them - it is a patient-responsibility transfer, not a payer denial.
Retroactive adjustment
A modeled later, downward recoupment applied to a small random fraction of clean claims - fabricated period-level variance.

Development notes

This report follows the Readmission Effectiveness Report's module pattern - its own SQLite file (data/revcycle.db), its own config, its own Synthea loader, its own admin area - rather than the ER Effectiveness Report's piggyback pattern. The reason: the denial/collections layer is a stochastic, config-tunable model that needs an explicit load or "Regenerate claim outcomes" step, and fabricated-data generation should not live inside a loader whose contract is faithful reshaping of Synthea.

Data pipeline: two stages

  1. Stage A - Synthea generation. The same CSV export that feeds the Readmission and ER reports, plus payers.csv and payer_transitions.csv (Synthea emits both by default). No new Synthea modules.
  2. Stage B - build claims + synthetic outcomes. One claim per ambulatory/wellness encounter with a stop time and a non-self-pay payer. Billed and allowed amounts are read from the encounter row; claim_status, denial reason, and all collection fields are assigned by app/healthcare/revcycle/denial_model.py under a fixed RNG seed, in encounter_id order so a reload reproduces the same outcomes. payer_transitions.csv is used only as a load-time validation cross-check, never a per-row join.

Tech stack

Python 3, Flask, SQLite, Jinja2, Chart.js, python-dotenv, gunicorn, and pytest. The synthetic-EHR source data is built offline with a local JRE and a Synthea checkout (generation-time only).