APP Program ROI Calculator
A sales tool for an APP education company that projects the return on enrolling a health system's NPs and PAs in its transition-to-practice program, based on benchmark data from past cohorts.
The client, an APP education company, runs a transition-to-practice program for Advanced Practice Providers (APPs), meaning Nurse Practitioners (NPs) and Physician Associates (PAs). The program helps new APPs get productive and confident in practice sooner. The pitch to health systems is that trained APPs see more patients and stay longer. This calculator puts numbers on that pitch. A prospective client enters a few details about their APP workforce, and the app projects the ROI they could expect in the first year.
Designing before building
Before writing any code, I designed the calculator in Figma and walked the client through the mockups. Changing a design is much cheaper than changing a build, so this is where we agreed on which numbers to feature, how much of the math to show, and how to be upfront that the results are illustrative, not guaranteed, while still making a clear case. Once the client signed off on the designs, I built the app from them.
A few inputs, one ROI number
The inputs are kept to the few numbers a practice manager would know offhand: how many APPs they have, average years of experience, average monthly encounters per APP, and current retention rate. Those numbers are matched against historical data from APPs who have already completed the program. The calculator finds providers who look like the client's own, with a similar amount of experience and a similar encounter volume, and projects how the client's APPs would grow based on how those providers actually did, with a 95% confidence range.
One codebase, two audiences
It works as a sales tool in two ways. The sales team uses an internal version during conversations with health systems, and an external version is embedded on the client's site so interested prospects can try their own numbers before they ever talk to anyone. Both come from one React codebase with two build processes. The internal build is secured with Azure Entra ID, and the external build is packaged to embed in their marketing site. An ASP.NET Core API on Azure handles the benchmark data and the calculations, and an Azure DevOps CI/CD pipeline deploys it all.
Rebuilding the projection logic
The projection logic started as a SQL script written by another team member. It produced the right numbers against the database tables, but it was slow, expensive, and didn't fit how the new app needed to use it: once per request, with each prospect's own inputs. I rewrote it as inline table-valued functions built from a chain of CTEs.
First came the reference data. I wrote a repeatable T-SQL script that cleans the raw monthly performance data. It drops providers with gaps in their records and periods dominated by zero-activity months and trims the extreme low and high months in each reporting period. Each provider is then ranked into quartiles by years of experience and monthly volume using window functions (NTILE, PERCENTILE_CONT), and the results land in indexed lookup tables that the projection functions filter against.
The functions take the prospect's inputs and run them through the CTE chain. CROSS APPLY and LAG() work out the quartile boundaries on the fly and place the client in the right experience and productivity buckets. From there the function matches comparable historical providers, measures each one's change from their baseline to their first program year (within fixed bounds) and returns a mean projection with a 95% confidence interval, along with its annual dollar value and ROI per provider.
Why table-valued functions
Table-valued functions were a good fit for a few reasons. They take parameters, so each run computes exactly the prospect's scenario instead of precomputing every possible combination. Because they're inline, SQL Server folds the whole CTE chain into the calling query and optimizes it as one, so the filters can use the lookup tables' indexes. They're read-only, so running a projection can't have side effects. And their output can be selected and joined like any table, which made the next step simple.
Measuring the program's real lift
That next step keeps the calculator from overstating the program. The API runs the same functions twice, once against APPs who went through the program and once against a benchmark group who didn't, then joins the results to calculate the net lift the program adds beyond normal growth. Dapper reads every result set back in a single round trip. And because the logic is driven by the lookup tables, the benchmarks can be refreshed by loading new data, with no code changes.
Showing the math
A headline ROI figure is only persuasive if people believe it, so the results show their work. The ROI quick report expands to show every step: projected encounters per APP, incremental revenue across the whole team, retention savings, total annual return, program cost, and the final ratio. Each line shows the inputs that produced it, so anyone reading it can follow the math.
Encounters and retention
The two drivers of the ROI each get their own tab. Encounters shows the projected lift in patient volume and what it means in monthly and annual revenue, alongside the benchmark match details and a chart of current versus projected encounters.
Retention compares the client's current turnover cost to the projected cost at the program's retention rate. Replacing an APP is expensive, so even a few points of retention add up to real savings. Participant testimonials sit underneath, putting a human voice next to the numbers.
From mockup to shipped app
The build stayed close to the approved designs, with a few changes along the way. The mockups had a wRVU tab alongside encounters. The benchmark data supported both, but after talking it through with the client, we dropped wRVUs and focused on encounters, since that's the metric their business model is built around. The specialty input came out too, because the benchmark data covered one main specialty and there was nothing to choose between. The single client name field grew into a lead capture section with name, business email, and organization, so when prospects use the calculator on the company's website, the client knows who's interested.