Arr waterfall
@ledgerly/arr-waterfall
Turn a monthly subscriptions export into an ARR waterfall: starting ARR, new, reactivation, expansion, contraction, churn, ending ARR, plus NRR and GRR. Writes markdown, CSV, and a per-customer movements file. Works offline from a CSV.
- Activity
- New: be the first to try it
- Installs
- 0 installs
- Likes
- 0 likes
- Clones
- 0 clones
- 1---
- 2name: arr-waterfall
- 3description: Build an ARR waterfall (starting ARR, new, reactivation, expansion, contraction, churn, ending ARR) with monthly and cohort NRR and GRR from a subscriptions or MRR export. Use when the user asks for an ARR bridge, ARR waterfall, net new ARR, NRR or GRR, "how much did we churn", board or investor ARR numbers, or hands over a CSV of MRR by customer by month.
- 4license: MIT
- 5---
- 7# ARR waterfall
- 9Turns "MRR by customer by month" into the ARR bridge finance teams and boards expect. The math is done by a script, so the numbers are repeatable and tie out every month.
- 11## Inputs
- 13Ask for one CSV, saved as `data/subscriptions.csv`:
- 15- `month` (2026-09 or 2026-09-01), `customer_id`, and either `mrr` or `arr`.
- 16- One row per customer per month while they pay. Several rows for one customer in a month (several subscriptions) are added together.
- 17- Months a customer is missing count as zero ARR.
- 19Where to get it: a billing system "MRR by customer" report, a revenue schedule from the books, or a spreadsheet with one column per month (reshape it to long format first and tell the user you did).
- 21If the user only has a list of subscriptions with start and end dates, build the monthly rows first (one row per active month, amount normalized to monthly) and show them five sample rows before running.
- 23## Steps
- 251. **Check the file.** Read the header and 10 rows. Confirm: which column is the amount, MRR or ARR, currency (one currency only; if several, ask for converted amounts), and whether amounts include one-time fees (they should not; ask to remove setup and services fees).
- 262. **Run the script.**
- 28 ```bash
- 29 node scripts/arr-waterfall.mjs data/subscriptions.csv --out out/arr-waterfall
- 30 ```
- 32 Options: `--from 2026-01` and `--to 2026-09` to limit the range.
- 333. **Read the outputs** in `out/`: `arr-waterfall.md` (summary), `arr-waterfall.csv` (one row per month, for a spreadsheet), `arr-waterfall.json`, and `arr-waterfall-movements.csv` (every customer movement, so any number can be traced).
- 344. **Sanity check before sharing.** The script confirms each month ties out. Also look for: a single customer driving most of a month's churn or expansion, a jump that looks like a data issue (a customer at 10x their usual amount), and reactivations that are really a renamed customer ID.
- 355. **Write the summary** for the user using the template below. Lead with ending ARR and net new ARR, then the driver that moved most.
- 37## Definitions (state these when sharing)
- 39- **New:** first month a customer ever has ARR.
- 40- **Reactivation:** a customer who had ARR before, went to zero, and came back.
- 41- **Expansion / contraction:** change in ARR for a customer active in both months.
- 42- **Churn:** a customer active last month with zero this month. Full amount counts as churn.
- 43- **NRR (monthly):** (starting + expansion - contraction - churn) / starting. New and reactivation are excluded.
- 44- **GRR (monthly):** (starting - contraction - churn) / starting.
- 45- **Cohort NRR / GRR:** customers active in the first month, their ARR in the last month over their ARR in the first. GRR caps each customer at their starting ARR. With 13+ months the script also reports trailing 12-month NRR and GRR, the number most investors mean by "NRR".
- 47## Output template
- 49```markdown
- 50## ARR, <first month> to <last month>
- 51Ending ARR: $X (net new $Y, +Z% over the period)
- 52Driver: <the biggest movement in one sentence>
- 54| Month | Starting | New | Expansion | Contraction | Churn | Ending | NRR |
- 55...
- 57Watch: <1 to 3 customers or patterns worth a look>
- 58```
- 60## Guardrails
- 62- Never edit the user's source file. Reshaped or cleaned data goes in a new file in `data/` with a clear name.
- 63- Do not mix bookings, billings, and recognized revenue. If the user is not sure what the export contains, ask before presenting the numbers as ARR.
- 64- If the script skips rows, say how many and why. Stop and ask if more than 2% of rows were skipped.
- 65- Customer names are business data: summarize, do not paste the full movements file into chat.
