#The challenge
Revenue was part fixed and part consumption-shaped, with a minimum committed volume and usage overage above that commitment. The CRM tracked a single current-ARR figure on the account and nothing else. Multi-year contracts stepped commitments up or down between years and there was nowhere to record that, so the ARR on the account was only ever accidentally right. Renewal opportunities were excluded from the pipeline because a renewal's contract value is not a net transaction — which meant a renewal that shrank an account produced no visible movement anywhere. Finance rebuilt the real picture by hand outside the CRM, every month.
#The approach
A revenue-recognition object under the account, not a formula on the opportunity
The structure is a custom object hanging off the account: a base contract plus monthly true-up rows covering committed volume, usage overage and fees. Entry is monthly and manual by design — the row volume is low enough that a fragile consumption integration would cost more than it returns, and the client explicitly wanted control over the numbers rather than hidden maths.
Commitments stamped by contract year at close
New opportunity fields capture the minimum commitment for each of up to five contract years, date-stamped, so current ARR only ever reflects the year actually in contract. Headroom was built past the typical term length on the reasoning that it is cheaper to build headroom than to retrofit it. Validation rules hide the year fields with no value so a short deal does not inherit a five-year page layout.
Separate the ARR types before netting them
Upfront, subscription and minimum-commit ARR are tracked as distinct types, each with its own change field. The reason is concrete: a renewal can shrink the subscription while growing the commitment, and an account-level net number hides exactly the movement finance needs to see. Product-level tracking was scoped but deliberately deferred, with the infrastructure left ready for a product-family dimension.
Model renewals as ARR movement, not as contract value
Recommended splitting renewal opportunity types into flat, expansion and contraction so renewal outcomes become queryable ('where are our renewal expansions this year?'). On a renewal close, the ending current ARR is stamped and the difference is written as a net ARR change by ARR type. A closed-lost renewal stamps the churned amount and reverses the ARR to zero with a churn date, so the account reads as a dated ARR history rather than a single current value.
Committed volume and overage move as one pool
The case finance cared about most: when a renewal raises the committed volume, a corresponding amount of usage overage has to come out, or the variable bucket double-counts. Modeled the two as a single variable pool with both a total net change and a within-category net change, so raising the commitment and reducing the overage nets correctly instead of producing phantom growth.
Automate the entry, not the judgement
Because the fixed components and the multi-year commitments are all known at close, they flow into the revenue-recognition records automatically when the opportunity closes — the finance owner does not create three entries for three corresponding changes. Variance and reported-ARR fields were offered as either calculated or manual and left where the owner wanted control. Field naming was treated as a review item for the client rather than a developer decision.
Handoff treated as part of the build
Shipped a monthly-logging screen flow and page layouts, recorded walkthrough videos for the finance team, a bulk-upload template for historical data, and a sandbox validation of the historical ARR backfill against a real sample dataset from the client before anything touched production. The production change set was then handed into the client admin's own sprint rather than pushed around them.
#Outcomes
One account view instead of a monthly spreadsheet rebuild
Historical ARR by month and by revenue type became readable directly from the account, which was the stated goal: one report a finance leader can pull without reconstructing it.
Contraction became visible
Renewals that reduce an account now produce a recorded net ARR change by ARR type rather than disappearing because renewal opportunities sit outside pipeline.
Multi-year deals stopped needing a footnote
Year-by-year committed volume with date stamps means a stepped contract reports its actual in-contract value rather than a blended or year-one figure.
Backfill validated before production
The historical ARR backfill was proven in a sandbox against a real example dataset, and the move-forward documentation was checked to cover historical entry before the change set was deployed.