Aditya Gaur
Work

Revenue engine

The billing platform

A billing system built on one split — the number that bills is never the number that merely displays — and the audit of my own dashboard that proved the invoice had been right the whole time.

Role
Solo — product, engineering, revenue operations
Timeframe
2024 — 2026
Status
prototype
Stack
PostgreSQL·Node.js·TypeScript·React
Outcome

Reconciled 19 revenue surfaces against the billing engine itself — four root causes, zero P0s, no surface ever mis-billed a customer.

  1. 001
  2. 002
  3. 003
  4. 004
  5. 005
  6. 006
  7. 007
  8. 008
  9. 009
Invoice
Dashboard

001

The manual month-end

Seventy-seven sheets

Once a month, someone opened a spreadsheet per client, per API, and started multiplying. Usage times rate, minus the sandbox rows, minus whatever had been verbally agreed and never written down, equals an invoice. There were, on a bad month, seventy-seven of these sheets, and the work of closing the books was the work of not losing track of seventy-seven separate arguments with yourself about whether a number was right.

It usually was. That's the part worth sitting with, because "usually" is not a word that belongs anywhere near an invoice. A spreadsheet does not fail loudly. It fails by quietly agreeing with whatever you typed into it, and the only check on that agreement is a person, on the last Friday of the month, tired, cross-referencing a rate card against a CSV export and hoping the two still describe the same product.

Four questions came out of watching that process happen a few times. What did we actually bill this client last month. What did that revenue cost us to serve. Which of these customers is unprofitable once you net the two. And a fourth, which a spreadsheet cannot answer even in principle: what are we serving right now and not charging for at all.

The fourth question is the interesting one, and it's worth saying precisely why a spreadsheet can't touch it. A missing row and a nonexistent row look identical. If an API call went out, hit production, cost real infrastructure, and was never priced, there is no line item anywhere that fails to reconcile. There is simply an absence, and an absence doesn't raise your hand. You can audit every number in a workbook and still miss the customer who isn't in it.

That gap is where the billing platform starts. Not "build a billing dashboard." There was already a dashboard, and it's one of the nineteen surfaces this page eventually audits against its own author's work. The actual brief was narrower and harder: stop treating "what we bill" and "what we show" as the same computation wearing two different fonts, because they had quietly become two different systems that happened to agree often enough that nobody had checked whether they had to.

The month-end pipeline

Settlement worksheet

Northwind Finance Limited · May 2026

InterfacePricedCalls₹ / callAmount
Tax statement pull7,214 calls · flat at 5.5372flat7,2145.5372₹39,945.36
Payslip extraction3,743 calls · flat at 4.1490flat3,7434.1490₹15,529.58
Voter ID verification7,807 calls · flat at 1.8867flat7,8071.8867₹14,729.81
Trade licence check4,599 calls · flat at 3.0617flat4,5993.0617₹14,080.76
Face match3,941 calls · flat at 2.7005flat3,9412.7005₹10,642.57
Company registry lookup2,227 calls · flat at 2.7091flat2,2272.7091₹6,033.07
Negative list check2,865 calls · flat at 1.9959flat2,8651.9959₹5,718.35
Email risk score2,374 calls · flat at 1.9801flat2,3741.9801₹4,700.66
Payment ID verification4,842 calls · flat at 0.9676flat4,8420.9676₹4,685.06
Identity number verification5,578 calls · whole volume at 1.3952 blendedwhole volume5,5781.3952 blended₹7,782.26
Settlement45,190 calls45,190₹1,23,847.49
One account’s month: 10 sheets, 45,190 calls, one settlement. Nine of these lines are volume times rate, which is what a spreadsheet is for. The last one is not — a whole-volume rate resolves on the period’s total, so it has no value at all until the month closes, and no day of the month holds a share of it. That is the line a hand-multiply cannot reach, and the same line that comes apart in the audit.

002

The founding split

One number bills, the rest display

Here is the decision everything else in this system is downstream of. A draft invoice is not a cached answer. It's recomputed from live usage every single time someone opens it. Rates change, sandbox windows close, a leak gets priced retroactively for the current period, and the draft simply reflects whatever is true right now. It has an opinion, and the opinion is allowed to be wrong for an hour, because nobody has been charged yet.

The moment an invoice is finalized, that stops. The computed lines are snapshotted into storage of their own and never recomputed again, ever, for any reason, because the customer has now seen the number. You can fix the pricing engine the next day and it will not reach backward and silently change what was already sent. If something was wrong, the correction is a new, visible row, not an edit to history.

DRAFTFINALIZED

That's the whole split, and it's also the operable form of this page's argument: before finalize, the number displays. After finalize, it bills. Everything downstream (the dashboard, the margin view, the leak detector) is describing the first kind of number, and it is allowed to be provisional in a way an invoice never is.

Which is why this page has two reading modes rather than one. Ledger is the invoice: settled, printed, done. Nothing on it moves, because ink dries. Console is the dashboard: fast, dense, and always exactly one query behind the truth it's approximating. The toggle below doesn't pick a color scheme. It picks which of the two numbers you're looking at, and you can leave it on Default and let each chapter show you the register the thing being discussed actually lives in.

Derive and finalize

Recomputed now

DRAFT

Northwind Finance Limited · May 2026 · read against today’s rates and trial state

₹1,08,317.91

one line suppressed · ₹15,529.58

As issued, 31 May 2026

FINALIZED

Northwind Finance Limited · May 2026 · snapshotted at finalize, never recomputed

₹1,23,847.49

10 lines, frozen

Same account, same closed month, same usage. The lower sheet is a live recomputation against today’s inputs; the upper one is what was actually sent. They differ by one line — an interface that has since been moved to a trial and now looks free, so a replay quietly refunds a month nobody asked to refund. The upper figure is frozen precisely so that cannot happen, and the correction for a genuine error is a new dated row beside it, never an edit to this one.

003

One request, priced

Resolving a single call

An API call comes in. Something has to decide, in well under a millisecond and with no room to shrug, exactly what that call costs. The answer is a chain, checked in a fixed order, where the first rung that applies wins and every rung after it is never consulted.

Is this client sandboxed for this specific API, as of today. If yes, the call is free, full stop, and nothing below this line runs. Is this call covered by a bundle the client has already paid for. If yes, it's covered, and the bundle's own accounting absorbs it. Does this client have a negotiated rate for this API. If yes, that rate applies. Falling through all three rungs lands on the catalog's base price for whatever plan the client is on.

And then there's a fourth outcome that isn't really a rung at all: the call matches nothing. No sandbox flag, no bundle, no negotiated rate — and no catalog entry, because the API code is new, or misspelled upstream, or was retired last quarter and something is still calling it. That call is priced at zero and logged as unresolved, which is a very different fact from "priced at zero because it's free." One is a decision. The other is a gap with a price tag of nothing, sitting in the revenue you never collected and never noticed you hadn't.

NOT BILLED — billable, priced at ₹0.00, invoiced by nobody. It is the single most important state this engine can be in, because a wrong number pages somebody eventually. A missing number does not page anybody, ever, on its own. Chapter 007 is what happens when this state accumulates quietly for long enough to become a real leak instead of a rounding error.

Pricing a single call

Resolution

resolved on rung 3 of 4

Account
Northwind Finance Limited
Interface
Identity number verification
As of
31 May 2026
Calls
5,578
  1. 1

    Is this account trialling this one interface, as of this date?

    no

  2. 2

    Is this interface part of a bundle the account already pays for?

    no

  3. 3

    Does this account have a rate for this interface, effective on this date?

    That rate applies, in whichever form the row carries: flat, graduated or whole-volume.

    applies

  4. 4

    Does the catalog carry a base price for this account's plan?

Rate applied

₹1.5644 / call

This line bills

₹7,782.26

A negotiated rate: resolved on rung 3 of 4, a negotiated rate. This line bills ₹7,782.26.

The essay's own volume-priced line. Two rungs are checked and miss before the third answers.

Where all 115 pairs land

rung 1 · a trial is open
1 pair
rung 2 · covered by a bundle
3 pairs
rung 3 · a negotiated rate
98 pairs
rung 4 · the catalog's base price
never taken
fell through
13 pairs

Fourteen pairs carry no rate, and thirteen of them fall through. The fourteenth is a bundle member, so a rung above answers first. A pair with no rate is not automatically a leak, and that one row is the difference between an audit and a list of complaints.

Four rungs, checked in this order, first match wins, over 115 real account-and-interface pairs. Three of these cases resolve and one does not, and the one that does not is the state worth remembering: it lights nothing, because there is nothing to light.

004

The four ways to charge for a byte

Four models, one view

Flat pricing is one number times one count, and it's the model everyone assumes is the whole problem — it isn't, it's the one nobody argues about. Tier pricing charges a different rate per unit within each band the usage crosses, the way income tax brackets work: the first ten thousand calls at one rate, the next forty thousand at a lower one, and so on, so the marginal rate steps down but every unit already billed keeps its own band's price.

Slab is the one that breaks people's intuition on the first try, including mine. Whole-volume pricing doesn't price each band separately. It looks at the total for the period, finds which slab that total lands in, and reprices every single unit at that slab's rate. Cross a threshold late in the month and the rate applied to units one through ten thousand can retroactively drop, because the whole month is being priced as one block, not as a running meter.

That has a genuinely strange consequence, and it's the reason slab gets its own curve in every chart of this system rather than being folded into tier: total revenue can fall at the exact moment usage crosses a slab boundary, before climbing again past it. Not flatten — fall. A customer who uses slightly more can be billed slightly less, for one specific slab crossing, and that is not a bug to be smoothed out. It's what whole-volume pricing is, contractually, and a pricing engine that can't render that drop hasn't actually implemented the model. It's implemented tier with slab's name on it.

Bundle is the fourth: a fixed allotment of calls across one or more APIs for a flat fee, consumed first, with overage falling through to whichever of the other three models governs what's left.

Four models, one settlement view, because a client on a bundle this month and a negotiated flat rate next month should never have to appear in a different report depending on which pricing engine happened to price their period.

The four models

Same month, priced three ways

One-time passcode check

32,000 calls

₹10,25,970

₹0

0

50,000

2,00,000

3,00,000

Flat₹3.4199 every call
₹1,09,436.80
Graduatedeach band's own rate, on that band's calls
₹97,680.00
Whole-volume₹3.0525 on every call
₹97,680.00

Inside the first band the two volume models are the same number to the paisa: ₹97,680.00 either way. Nothing distinguishes them yet.

The fall

At 50,000 calls whole-volume bills ₹1,52,625.00. At 50,001 it bills ₹1,22,102.44 — ₹30,522.56 less for one more call, and it does not climb back past the earlier figure until 62,500. Not a rounding artefact and not a boundary to smooth away: it is what whole-volume pricing contractually is, and an engine that cannot render the drop has implemented graduated pricing with the other name on it.

The fourth model: a bundle

May 2026

Three interfaces billed as one product at one agreed price. The anchor line carries all 18,182 calls; the other two bill nothing, and those two zeroes are not gaps. A bundle has no curve on the axis above because its answer does not vary with one interface's volume, which is exactly why it is a fourth model and not a fourth rate.

Credit bureau pullanchor
8,575 calls
₹2,02,366.56
Device fingerprint
6,640 calls
₹0.00
Address geocoding
2,967 calls
₹0.00
One interface on one real bracket schedule, with thresholds at 50,000 and 2,00,000 calls. Drag the volume. Graduated and whole-volume agree to the paisa inside the first band and part company the instant it is crossed, which is the non-obvious thing about volume pricing and the reason a system needs both. The fourth model is not a curve, and the panel below says why.

005

Twenty-three tables, one pattern

The schema

Twenty-three tables sounds like a lot until you notice most of them are the same idea, applied to a different subject: nothing in this schema is ever updated in place if updating it in place would mean the past quietly changes shape. Rates, sandbox flags, client tiers: all of it is effective-dated, which means every row carries the date range it was true for, and asking "what rate applied on the 14th" is a query against history, not a lookup against the current value with your fingers crossed that nothing's changed since.

That single pattern is what lets a draft invoice for last month get recomputed today and still land on exactly the number it would have shown last month, because every input it reads resolves against the date being billed, not the date the query happens to run.

Invoice numbers come from a table of their own, not from an auto-incrementing column, and the distinction is not pedantic. An invoice number is a legal artifact. A gap in the sequence has to mean something happened (a voided draft, an audit trail entry), and a reused number can never happen, so the sequence is allocated transactionally as its own concern rather than trusted to whatever the database's counter does under concurrent writes.

Adjustments are rows, never edits. You cannot make a finalized invoice retroactively say something different. You can only append a new, dated, visible correction beside it — the same discipline the derive/finalize split enforces at the invoice level, pushed one layer down to the line level. It costs an extra table. It buys an invoice that can be fully reconstructed from its own history, which is the actual definition of an audit trail, as opposed to a change log that happens to exist.

The effective-dated pattern

Replay

Payslip extraction

May 2026

June 2026

July 2026

1 January 2026rate set — ₹4.6411 per hit

1 June 2026trial opens — billing suspended for this interface only

1 July 2026rate revised — ₹5.1052 per hit

₹4.6411 / call

trial — not billed

trial — not billed

3,743 calls

7,195 calls

148 calls

₹15,529.58

₹0.00

₹0.00

rate dated 1 January

trial opens 1 June

trial still open — the rate dated 1 July has never applied

Negotiated rates
103 dated rows
Vendor costs
32 dated rows
Trial windows
1 dated row
Bundle prices
1 dated row
One interface on one account, across three closed periods. Every row resolves against the date being billed rather than the date the question is asked, which is why the first period still answers ₹4.6411 — a rate set in January, superseded in July, and permanently correct for May. Nothing was updated in place, so nothing about the past changed shape.

006

Two migrations, one lesson

Naming as infrastructure

Two migrations in this schema do no computation at all. They exist purely to fix what things are called, and they are, without much competition, the best product-management artifacts in the whole codebase — because a vocabulary correction that has to run as a migration is a vocabulary correction that has been taken seriously enough to be treated as infrastructure rather than a message asking everyone to please start saying it differently.

The lesson underneath both: UI vocabulary and schema vocabulary are allowed to diverge, on purpose, permanently. A user should never have to know that the row backing "Group" is still, at the storage layer, a client. Pretending otherwise is how naming debt turns into rename debt, which is strictly worse.

The same discipline shows up one level down in what a leak is allowed to become. A leak is a (client, API) pair with usage on days that had no price in effect: call it a rate that should have existed and didn't. Once you price it going forward, the historical hits are still unpriced, and they always will be, because they're in the past and the past doesn't take new invoices. So the system grew a third state beyond "wrong" and "fixed": acknowledged. Dismissing a leak suppresses only its historical classification. A pair still leaking today can never be dismissed, no matter how thoroughly its history was acknowledged. The product had to learn the difference between a problem that's solved and a problem that's simply no longer actionable, and refuse to let the second one impersonate the first.

007

Three ways revenue goes missing

What leaks

A leak, in this system, is any usage that generated cost and generated no invoice line to cover it. There are three distinct shapes that takes, and they are not equally dangerous, which is the entire reason they're modeled as three states instead of one severity flag.

The first is a rate gap: usage on days with no price in effect for that (client, API) pair. It has a floor: you can see exactly what accrued and price it, even retroactively, even if the fix arrives late.

The second is sandbox drift, and it's a lifecycle problem rather than a pricing one. Sandbox began as a single bit on the client record: on or off, for the whole account. The actual request that came in was narrower: an existing paying customer wanted to trial one new API without being billed for that API specifically, while everything else on their account kept billing normally. A single flag can't express "free for this one thing, billed for everything else," so sandbox became two effective-dated rows per (client, API) pair — one opening the trial, one closing it at the go-live date — and billing begins exactly on go-live, with nothing retroactive charged for the trial window. The lifecycle transition isn't a feature bolted onto sandbox. It is sandbox, correctly understood.

The third is the one with no floor at all. Vendor API codes get retired, duplicated under a new name, or renamed upstream without notice, and usage keeps arriving tagged with whatever code the caller last knew. A rate gap at least tells you what it's missing. A dead-code hit doesn't resolve to anything. It's not underpriced, it's unrecognized, which is why the catalog has its own reconciliation pass: one transaction merges duplicate codes onto their survivor across five child tables, deactivates retired codes that still have live data attached rather than deleting them outright, and upserts the canonical name and its known aliases so the next hit resolves correctly the first time.

The three leaks

Detectors

83,647 calls sizable · 91 not

Three detectors, none open. The shapes are the argument: two hold a level you can read, and the third has nothing underneath it.

33 interfaces in the catalog, 30 of them active, and 45 calls that resolved to none of them. Those last ones are countable and unplaceable at the same time, which is the whole of the third class.

Three shapes the same failure takes, against 8,81,284 recorded calls. Two can be sized and closed by writing a dated row. The third is the smallest of the three and the only one with no floor, because a call that resolves to no interface cannot be priced — and a missing number, unlike a wrong one, never pages anybody.

Three vessels. Two of them hold a level you can read and act on. The third has no floor, which is the honest way to draw "we don't yet know how much this is costing us" — not as a number, as a shape with nothing underneath it.

008

Proving my own dashboard

Auditing the dashboard against the invoice

Everything up to here has been the engine that produces the number that bills. This chapter is about the other number (the one on the dashboard, the one an operator actually looks at day to day) and whether it has been telling the truth.

So I built a gap register: nineteen separate revenue surfaces across the product, each one reconciled line by line against the billing engine itself, treated as the one oracle every other number owes an explanation to. Nineteen surfaces is a lot of places for a dashboard to quietly diverge from the thing it's summarizing, and for four thousand words this page's own reconciliation rail has shown you exactly that — the invoice figure and the dashboard figure, agreeing, chapter after chapter, closely enough that you'd stopped checking.

Watch it now.

Invoice
₹1,23,847.49
Dashboard
₹1,16,065.23

The gap is one line, and it is the whole-volume line from chapter 004. Whole-volume pricing resolves on the period's total, which means it has no correct value on any single day of that period — the rate isn't known until the month is. So a surface that builds its number by summing days has nothing to put in that line, and what it puts there instead is zero. Not a wrong formula, and not a boundary condition. A number that does not exist at the granularity the surface insisted on reading it at, rendered as a confident nought and then added into a total. The invoice was never wrong — it prices the period, once, the way the contract says. The dashboard was reading its own approximation of the invoice's logic, and the approximation had a seam exactly where the model refuses to be daily.

ZERO P0s — nineteen surfaces, four distinct root causes across all of them, and not one instance of a customer being billed the wrong amount. Every gap this audit found was a display gap: a number an operator looked at that didn't match the number that actually went out. That's a real problem (a dashboard an operator can't trust is a dashboard they eventually stop consulting, which defeats the entire point of having one), but it is categorically not the same problem as an invoice being wrong, and conflating the two is exactly the failure mode this whole page has been arguing against since chapter 002.

The gap register

Reconciliation register

ZERO P0s

All 19 findings, as they arrived — 13 displaying a wrong number, 6 cosmetic or latent, and none of them a customer billed the wrong amount.

19 surfaces reconciled
SurfaceWhat divergedSev
Invoice listThe revenue column, on every draft rowEach row should restate its own invoice's total. Every draft row on every account read zero instead — the entire column, blank, next to invoices that were correct.severity P1
Dashboard headlineRevenue and margin over a multi-month windowShould be the sum of each period's own settlement. Understated whenever the window spanned more than one period; a single month was exact to the paisa.severity P1
Money at riskBooked loss where delivery cost exceeds the price chargedShould count only dates an invoice covers. Included a month with no billing period open, and labelled the result actual rather than projected — the worst combination available: a soft number presented as a hard one.severity P1
Money at riskUnpriced usage — the rate-gap leakSame unguarded window. Over-reported both the hit count and the rupee figure by including usage from an un-invoiced month.severity P1
Money at riskUsage that resolves to nothing — the silent lossSame unguarded window, and the largest of the three classes by volume, so the same mistake cost the most here.severity P1
Per-day revenue chartOne client's month, summed across its daysShould reconcile to that client's invoice. Fell short by exactly the volume-priced line, which the chart reported as zero on every single day of the month.invoice₹1,23,847.49shown₹1,16,065.23short by₹7,782.26severity P1
Per-day revenue chartThe whole book, against the headline tile above itChart and headline sat on one screen computing revenue two different ways — the headline added volume pricing back, the chart did not. They could not agree.invoice₹13,01,490.63shown₹12,40,815.87short by₹60,674.76severity P1
Client list and top moversRevenue per client over a custom windowUnderstated for volume-priced clients over multi-period windows. The default comparison happened to be two single months, so the ranking a reader saw first was correct and only a custom range exposed it.severity P1
Client detailThe headline total, against the breakdown printed under itThe breakdown was right and the headline above it was wrong, on the same screen, for the same client, over the same window. Everything derived from the headline — average price per hit, share of book, the leak figure — inherited it.severity P1
Interface listRevenue and average unit priceVolume-priced interfaces contributed nothing, so their revenue was understated and the average unit price computed off it was meaningless.severity P1
Interface detailTop consumer and share of interface revenueRanked by a revenue figure that reads zero for volume-priced usage, so the largest consumer of one interface by volume appeared near the bottom of its own list, and the share denominator omitted its revenue entirely.severity P1
Interface listMulti-month totalsWrong in both directions at once: flat interfaces over-reported by including an un-invoiced month, while volume-priced ones under-reported by contributing zero.severity P1
Account totalsThe list, the detail page, and the invoices underneathThree surfaces, three different definitions of one account's revenue — one included trial members, one excluded them, and the invoice had its own rule. Only the detail page reconciled. The same total also reported an un-invoiced month as revenue.severity P1
Projected month-endThe projection's base figureNo error of its own — it extrapolated the headline's under-count faithfully and was still labelled a month-end projection. Corrected the moment the headline was.severity P2
Money at riskVolume repricing folded into the margin watchConsumes a pooled window figure, so it carries the pooling error — but inert on today's data, because no volume-priced pair yet carries a delivery cost high enough for the comparison to fire. A latent finding, recorded as latent.severity P2
Money at riskConsistent exclusion of trial usage across all three classesTwo of the three risk classes exclude trial usage; the third cannot, because it reads usage that resolves to no client at all, and unattributed rows have no trial state to check. Accepted: the figure is presented as an estimate.severity P2
Interface detailPrice variance across clientsReads the flat rate only, and volume-priced clients store no flat rate — so they were structurally invisible to the variance, not merely missing from it.severity P2
Interface detailThe per-day activity seriesRendered a revenue line at zero for every day of a volume-priced interface, implying no revenue where substantial revenue bills. Hits rendered correctly beside it, which made the zero more convincing, not less.severity P2
Invoice listThe draft line countCounts interfaces rather than invoice lines, so a bundled account would show more lines than its invoice prints. Latent — masked entirely by the blank revenue column above it.severity P2

Checked and held — 7 reconciliations an adversarial pass tried to break and could not

  • A single month's dashboard headline — exact to the paisa against the invoice.
  • The active-client count, including clients whose only usage is volume-priced or bundled.
  • The trial-usage guard on the headline figure, consistent across both halves of the computation.
  • The default movers comparison — two single months, so the pooling error cannot arise.
  • The per-client interface breakdown and its volume-pricing tag: the correct reference the headline should have matched.
  • Bundle collapse, and the money arithmetic end to end — exact to the paisa on every account tested.
  • Dismissed-leak exclusion, and the unpriced-pair indicator on the client list.
Every revenue surface in the product, reconciled against the billing engine treated as the one number the others owe an explanation to. Filter by cause and watch the scatter collapse: 19 findings, 4 root causes, 0 of them a billing error. The two rows carrying figures are the two this data reproduces exactly; the rest state the divergence in words rather than borrow a number from elsewhere.

009

The reader's own client, closed out

Your invoice

Nine chapters, and the rail beside them has been running one client's month the whole time: agreeing with itself, then visibly not, then agreeing again once chapter 008's fix lands. That's not a demo account. It's every account this engine has ever closed out, compressed into one number you've been watching without being told to.

₹1,23,847.49

That's the invoice. It was correct in chapter 002 and it is correct here, because it was never the number in question — the dashboard was. Closing this page's own argument with a settled figure rather than a diagram is the point: a billing system's job is not to be interesting to look at. It's to produce this number, the same way, every time, and to be honest the one time in nineteen it briefly wasn't showing it correctly somewhere else.

What I'd build differently, with the whole system in front of me rather than three years into it: the sandbox lifecycle and the leak-dismissal lifecycle are the same shape (an effective-dated transition with a state that can't be un-acknowledged retroactively), and they were built eighteen months apart as two separate features before I noticed. One generalized primitive, built once, would have made chapter 007's three leak classes and chapter 004's sandbox transitions the same code path instead of two implementations that happen to agree. That's the honest cost of learning a domain by building it: the right abstraction is usually visible only after you've built its two separate cases and can finally see they were one.

Your invoice

Statement of this session

NOT BILLED

Nothing recorded. This one statement is the only thing on the page that needs scripting; every chapter above it, and every figure in them, is already here without it.

Every line you reached the end of, itemised the way the month was. The quantities are words of prose, counted from this page as it rendered rather than stored. There is no amount column, because there is no rate for reading a chapter and this is not the page to invent one on.