Tool · For nonprofits and funders

Cost-Effectiveness Model Kit

Build a cost-per-outcome model, explain its assumptions and sources, retain immutable versions and check an exported calculation in another browser or with the command-line verifier.

Build a cost-effectiveness model

5,000 simulated draws, run in your browser. Nothing is sent anywhere.

Name one unit of the outcome, like “meal served” or “extra school day attended”.
Total program cost ($)

Everything the program spends, including staff, systems and overhead.

People reached (people)

How many people the program reaches.

Chance it works as intended (%)

From 0 to 100. Your estimate that the program has its effect at all.

Effect per person, per year (outcome units)

Units of the outcome each person gains in each year the effect lasts.

Years the effect lasts (years)

For a one-time outcome, enter 1 in all three boxes.

Share that would have happened anyway (%)

From 0 to 99. How much of the outcome would have happened without the program.

One value. How much less each later year of effect counts: at 4%, the second year counts about 96% as much as the first. Enter 0 to count every year the same. Whether the future should count less at all is Open Problem 13.
The same inputs and seed repeat this runtime’s calculation. Another platform may produce different complete-array fingerprints. Change the seed to explore simulation variation.

Enter a low, likely and high value for every input, or load the example, then run the model.

How it works. Cost per outcome = total cost ÷ (people reached × chance it works × effect per person per year × discounted years × the share that would not have happened anyway). Each draw picks every ranged input from a triangular distribution between your low and high values, peaking at likely. The first year of effect counts in full and each later year counts 1 ÷ (1 + discount rate) as much as the one before.

Its limits.

  • The interval only reflects the uncertainty you entered. Ranges that are too narrow give an interval that is too narrow.
  • Inputs are drawn independently. In real programs some move together, such as cost and people reached, which can make the true range wider or narrower.
  • The chance it works scales the outcome, so the result is an expected value. It hides the real chance of achieving nothing.
  • It counts one outcome. Side effects, harms and benefits to people the program doesn’t reach directly are left out.
  • Work at the source end of the depth scale rarely fits a model like this: Open Problem 3, Measuring the Source.

Private local workspace

Reproducible model bundles

Record one outcome, its assumptions and the exact calculation. Inputs remain user descriptions. A reproduced calculation is not measured impact or independent review.

Your writing stays in this browser until you deliberately download it. This desk has its own local library. The public model registry is empty.

Private controls are disabled until this workspace opens. JavaScript is required.

Literal inputs

Copying reads only the calculator’s current visible inputs. It does not copy a saved model or establish a source. No example loads automatically.

Total cost, USD
People reached
Chance, percent
Outcome per person
Years
Happening anyway, percent

Zero is a value. Unknown inputs need an explicit authored assumption before freezing; blank does not become zero. Chance scales expected outcomes. Only USD and one outcome are supported.

Authored context and assumptions
Sources and point bases — exact JSON writing

Unfinished JSON stays literal when saving a draft. Freeze parses it. Sources is an array, sourceModel is null or its explicit mapping. Every row basis is an object with low, likely and high PointBasis objects; discountBasis is one PointBasis. Each point is {"kind":"user-assumption","sourceIds":[],"rationale":"Your reason"}. Source-informed points name up to three source IDs. Dates use {"precision":"year","value":"2026"}, month or day precision.

A source description has id, title, publisher, url, locator, published, accessedOn, access, license, note and checksum. Optional values use null. Access is public, restricted, not-shared or unknown. A local checksum describes bytes you chose; it does not verify a claim or redistribution rights.

Use null for an unknown checksum, or {"kind":"declared","sha256":"64 lowercase hexadecimal characters"} for a declared hash. The checksum chooser creates local-bytes claims. A claimed source-model mapping is {"sourceId":"your-source-id","artifactSha256":"that source checksum","interpretation":"Your explicit mapping to these six inputs"}. This description does not reproduce another source’s model. Unused sources need an explanation in note.

Source file checksum

Choose an existing source ID from your sources JSON, then one file up to 8 MiB. Only its local checksum enters the source description. The file body and path are excluded.

 
Local history

Stored and restored versions are declared historical results, not recalculated on this browser. Local copies retain their source; amendments append a version.

 
Inspect a file

Choose one selected bundle or full private backup, up to 2 MiB. Inspection has no saved effect. Supplied engine text stays inert; an unknown engine cannot be recalculated or copied. Keep the original file for exact raw-file recovery.

A match confirms this selected result on this browser; another runtime may differ in its complete-array hashes even when summaries agree.

No file inspected.

   
Saved state and recovery

Retry covers the original reviewed candidate, even if you have edited the form since. Reload deliberately replaces local writing. Clear removes only this desk’s key. Undo is available only for the most recent successful Clear or Restore.

How it works

A cost-effectiveness model asks one question: how much does each unit of good cost? The kit breaks that question into parts you can reason about, and asks for a low, likely and high value for each:

  • total program cost
  • people reached
  • the chance the program works as intended
  • the effect per person, per year, in an outcome unit you name
  • how many years the effect lasts
  • the share of the outcome that would have happened anyway

One more input, the annual discount rate, takes a single value.

The kit then runs the model 5,000 times. Each run, or draw, picks every input at random between its low and high values, most often near likely. The spread of the 5,000 answers shows how uncertain the result is, given what you entered.

You can save models in your browser, load them again, download the inputs and results as a CSV file, or start from a clearly fictional example.

Plan output costs in a spreadsheet

Download the formula-bearing cost-per-output planner. One editable worksheet combines a defined output, inclusive planning period, nominal USD cash costs, source notes and explicit bounds. Its included example is fictional. The formulas and native LibreOffice recalculation cases are public.

This separate planning method counts outputs, not measured benefits. It does not import bundles or reproduce the frozen simulation below. Unknown inputs stay distinct from zero, and conditional bounds are not probability intervals.

Record and reproduce a model

The reproducible model workspace keeps the calculation with its purpose, population, period, USD cost basis, sources and assumptions. Start with an explicitly chosen illustrative example, copy the calculator’s current inputs or write your own. A copied input is still an authored assumption; it does not establish a published source.

Save a draft to keep unfinished writing, including unfinished source JSON. Freeze a version after reviewing the full candidate. Freezing runs the fixed calculation and retains the exact inputs, assumptions and result. Amend the current head to append another version with a reason; earlier versions stay intact. A local copy starts another draft and retains its source-version reference.

Export a selected version to share one complete model. Export a full private backup to retain the local library and saved draft. Both show the complete outgoing content before download. Visible edits need a separate save or unfinished-form recovery; a backup does not silently include them. Review source descriptions before sharing them, since they may contain private writing. Source files are never attached. An optional local checksum describes the exact bytes you chose and establishes no claim about their accuracy or rights.

Choose a selected bundle to inspect its declared contents, then deliberately recalculate it here. A match means this installed interpretation reproduced the recorded numerical result on this browser. A mismatch shows the differing fields and fingerprints. An arithmetic refusal shows the operation that could not be represented safely. A mismatch or refusal permits only an explicitly acknowledged draft copy. Unsupported interpretations stay inert. Reading a source description, restoring history or matching a calculation supplies no independent source review or measured impact.

Clear and Restore require a complete review and acknowledgement. Their guarded Undo is available while its exact saved state remains current. If saving fails, Retry keeps the original reviewed candidate; newer writing remains separate. If another tab changes the saved string, keep recovery copies before deliberately reloading.

Contributors can also check one selected bundle from a cloned repository:

npm run model:verify -- /absolute/path/model-selected.json --json

The verifier reads one local regular file up to 2 MiB and uses the installed interpretation in a bounded worker. It accepts no URL or supplied executable source. Its result distinguishes a match, mismatch, invalid file, unsupported interpretation, arithmetic refusal and unavailable runtime. The comparison is exact on this runtime; a file from another platform can differ in its complete-array hashes even when displayed summaries agree. This is a calculation check, not an assessment of a charity.

The method

The formula. Cost per outcome = total cost ÷ (people reached × chance it works × effect per person per year × discounted years × the share that would not have happened anyway).

Discounting. The first year of effect counts in full. Each later year counts 1 ÷ (1 + rate) as much as the one before, so at 4% the second year counts about 96% as much as the first. A rate of 0 counts every year the same. Whether future outcomes should count less at all is Open Problem 13, Discounting the Future.

The draws. Each input follows a triangular distribution: it never falls below low or above high, and it is most likely near likely. Draws come from a seeded random number generator. Admitted inputs and their seed determine the calculation under the pinned interpretation on this runtime; an explicit reproduction checks whether another supported runtime matches its numerical fingerprints. Changing the seed shows how much the results move by chance alone.

The outputs. The headline is the median cost per outcome, the middle of the 5,000 draws, with a 90% interval: 90% of draws fall between its two ends. The histogram shows how the draws spread. The sensitivity chart takes one input at a time from its low to its high value, with every other input at likely, and shows how far the cost per outcome moves. Its longest bar shows the largest change in this calculation when that input varies alone; it does not determine a research priority.

What it isn’t

It isn’t a measurement. The model can only be as good as its inputs, and the interval only reflects the uncertainty you put in. Ranges that are too narrow give results that look surer than they are.

It makes simplifications you should know about. Inputs are drawn independently, though in real programs some move together. The chance of working is treated as a scaling factor, so the result is an expected value that hides the real chance of achieving nothing. It counts one outcome, so side effects, harms and spillovers to other people are left out.

A cost per outcome also isn’t the whole picture. Overhead ratios tell you even less, which is the Overhead Myth, but cost-effectiveness favors what can be counted. Work at the source end of the depth scale rarely fits a model like this one. That is the Measurement Gap at its widest, and Open Problem 3, Measuring the Source.