TL;DR — Real bills are rarely one line. Submetering and RUBS bill the same utility completely differently. Tiered rates, taxes that read different charges, and late fees that fire only sometimes are all normal, not edge cases. A pricing engine needs five specific capabilities to model this correctly — and Billspree’s Pricing Template and Pricing Module architecture is built to satisfy exactly them.
A quick note on words. In a billing system, “pricing” or “rating” means something specific. It does not mean deciding what something should cost. That decision — based on production cost, margin, or the market — already happened somewhere else. Here, pricing or rating means something narrower. Pricing or rating is not about deciding what to charge. That decision is already made. Pricing or rating takes two things that already exist — the rate, and this cycle’s usage — and calculates the number the customer actually owes.
The Pricing Ecosystem
A bill is not always one simple line: total usage, a rate, a charge, a tax, done. Some bills are a real puzzle. A statement can measure more than one thing. Electricity and water might both be on the same bill. Each has its own usage number and its own rate. The rate itself might not be one number. The first block of usage can be priced one way, the next block another way, for as many blocks as the business needs. Tax is not always one line either. One tax can apply to one specific charge, like a state tax on the electricity part. A second tax can apply to a different charge on the same bill, like a local tax on the water part. This second tax has its own rate. It is calculated on the water charge, not on the electricity charge, and not on the whole bill. A customer reading the bill wants to see each charge and each tax listed separately. Then they want the two taxes added into one total, so the bottom line means something. On top of all this, there is often a late fee. It does not show up most months. It only appears once a previous bill goes unpaid past its grace period.
None of this is unusual. Nobody designed a bill to look this way on purpose. This is just what billing looks like once it reflects how a real service, in a real place, actually gets used, priced, and taxed.
Look across many bills, and the same small cast keeps showing up. No two businesses put it together the same way, but the pieces repeat: Usage — whatever actually gets measured. A rate — sometimes one number, sometimes a slab. The charges a business is actually owed for the cycle. Tax — sometimes more than one, each reading whatever it is meant to tax. A discount, when there is one to give — loyalty, volume, negotiated. A late fee, active only when it needs to be. A total — the one number that adds it all up into something a customer can read. This list is not closed. A business can always need something not on this list. A real bill needs room to add more.
That same cast does not produce the same numbers for every customer. The same service — electricity, say — can be billed under one rate for a residential account and a different rate for a commercial account. Same pieces, same bill structure, different numbers, because the customer is different. Tax can work the same way. The examples below show this directly: the residential account’s tax is one flat percentage, but the commercial account’s tax is two separate taxes, calculated two different ways. Who is being billed is not itself a line on the bill. But it decides which version of every other line applies.
Pricing Examples
One of those pieces — usage, “whatever actually gets measured” — is not always as simple as a meter reading. There are two real approaches for a residential utility account. Submetering: a real meter sits on each unit. RUBS: there is no meter, and a master bill gets divided by a ratio instead. It is worth working through both with real numbers.
Submetering
Here is what a submetered account looks like on an actual invoice:
Residential Electric — Submetered Unit
Usagemetered620 kWh
Rateper unit$0.14 / kWh
Chargeusage × rate$86.80
Discountloyalty−$5.00
Tax6%$4.91
Total$86.71
A real meter sits on this specific unit. It is not a master meter shared across the whole property. Look at where each number comes from. One number stands apart: usage. Nobody set “620 kWh” in advance. It is just what this meter reported that month. Everything else on that line — the rate, the charge, the discount, the tax — is something the plan has to produce on its own, no matter what usage shows up.
Submetering ranges from that simple case to something much more layered. The utility did not change — the customer did. Here is a residential account and a commercial account, on the same service, billed under two different rates:
Plan A — Submetered Residential
Usagemetered620 kWh
Rateflat$0.14 / kWh
Chargeusage × rate$86.80
Discountloyalty−$5.00
Tax6%$4.91
Total$86.71
Plan B — Commercial Electric
Usagemetered1,400 kWh
Ratetieredrule-based
Chargeusage × rate rule$207.00
Surchargegrid infra, 2% of Tier 1$1.20
State Tax6% of charge+surcharge$12.49
Local Taxflat$2.50
Total$223.19
Plan B’s Rate row is a single component, but that one component holds a rule with three conditions. Here is what that rule actually contains:
Plan B — Rate Rule (3 conditions, first match wins)
Usage ≤ 500 kWh$0.12 / kWh
500 < Usage ≤ 1,000 kWh$0.15 / kWh
Usage > 1,000 kWh$0.18 / kWh
Both plans have a Rate component. But the two Rates work in completely different ways. Plan A’s rate is a fixed value: one number, filled into one component. Plan B’s rate is a rule. It is still one component, but it has three conditions attached to it. Usage up to 500 kWh uses one formula. The next 500 kWh uses another. Anything past that uses a third. The system checks these conditions in order and stops at the first match. Either way, the component posts one $207.00 charge. The tiers live inside the rule, not as three separate line items. This is what “rule-based” gives you: one component can hold something as layered as a three-tier slab, without needing a separate component for each tier. A rule can also look beyond its own usage or its own conditions. It can reach into other components. Plan B’s State Tax is not computed from usage at all. It takes the Charge, adds the Surcharge, and applies 6% to the sum. Local Tax, right below it, ignores all of that. It is not a percentage of anything — just a flat $2.50. Three components. Three different formulas. Three different things each one actually looks at. State Tax’s rule, spelled out:
Plan B — State Tax Rule
State Tax(Charge + Surcharge) × 6%
RUBS
A RUBS unit has no meter at all. There is nothing to multiply a rate against. What it has instead is a share: a ratio, usually a blend of square footage and occupant count. That ratio applies against the property’s master bill. The master bill is not set once, like a rate card value. It has to be entered fresh every cycle, because the real utility cost behind it changes every cycle too.
Unit 204 — RUBS Allocation
Square Footageof property900 / 18,000 sqft
Occupantsof property3 / 60
Ratioblended5.0%
Master Billthis cycle$3,400.00
Unit Share$170.00
Unit 112 — RUBS Allocation
Square Footageof property600 / 18,000 sqft
Occupantsof property1 / 60
Ratioblended2.5%
Master Billthis cycle$3,400.00
Unit Share$85.00
Both units use the same blended formula, just with different inputs:
RUBS — Blended Ratio Formula
Ratio0.5 × (Unit Sqft ÷ Property Sqft) + 0.5 × (Unit Occupants ÷ Property Occupants)
Unit ShareRatio × Master Bill
Same building. Same master bill. The same $3,400.00 number feeds both units. But the two results are completely different. What is actually fixed here is not the bill — it is each unit’s ratio. Unit 204 is bigger and has more occupants, so it absorbs more of a cost that neither unit actually metered. That is the whole mechanic: no usage anywhere in the chain, just a ratio and a shared number that has to be refreshed by hand every cycle.
What This Complexity Demands From a Pricing Engine
What would it actually take to model everything shown so far? Five requirements. Each one is already proven necessary by an example already on this page.
Capability: Must help in adding new components
Start with the least glamorous requirement. Whatever does this modeling cannot assume it already knows every piece a bill will ever need. The Pricing Ecosystem already made this point: the list of usage, rate, charges, tax, discount, and total was not closed on purpose. A business needs to define a new charge, a new tax, or a new fee the day it actually needs one. It should not have to wait for someone else to ship a feature for it.
Capability: Must help in defining output logic
Whatever piece already exists — new or original — cannot be locked into one shape either. A component needs the ability to hold real logic, not just a stored value. And that logic often needs to be conditional: different formulas for different situations. Rate proves this. In the examples above, the same kind of slot held one flat number for the submetered residential unit. For the submetered commercial unit, it held a rule with three conditions instead — usage up to 500 kWh, the next 500 kWh, and everything past that, each with its own formula. Nothing about being called “Rate” forces either shape. The business decides that each time. The system should not decide it up front.
Capability: Must help components reference each other’s output, and resolve to nothing without error
Once those numbers exist, the pieces built from them are not independent of each other. A tax that only applies to one specific charge has to read that charge directly, not the whole bill. This is the same way a real state tax or a real franchise fee works on an actual utility statement. Some pieces are only sometimes relevant. A late fee has to sit there, get checked every cycle, and come back with nothing to charge most of the time. That should not count as a failure or need a special case to work around it. Here is the same account from Submetering, the residential unit, on two different cycles:
Late Fee — Most Cycles
Previous Balanceunpaid$0.00
Days Overduevs. 15-day grace period0
Late Fee$0.00
Late Fee — Bill Went Unpaid
Previous Balanceunpaid$86.71
Days Overduevs. 15-day grace period20
Late Fee$1.30
Same account, same Late Fee component, same condition checked every cycle: is there a previous balance, and is it past the grace period. Most cycles the answer is no, and the component correctly produces zero. On the one cycle where the answer is yes, the exact same component produces a real charge, with no special handling for either case.
Capability: Must help vary logic by customer type
Pricing does not only respond to usage. It also responds to who the customer is. The submetered examples above already show this. Residential and Commercial are not different services. They are the same service, billed differently, because the customer is different. That difference can live in one of two places. It can sit inside a single component, as a condition. There is only one Rate component. Its rule has a condition — is this account residential or commercial — and that condition decides which formula’s output the component uses. This is the same mechanic as a tiered rate: one component, one rule, a condition decides the output. Or the difference can sit across two separate plans. Each plan has its own Rate, but they share everything else — the same Usage tracking, the same Tax logic, the same Late Fee behavior. They only diverge where they actually need to. This second option is where reuse stops being optional. Without a way to share the parts that are genuinely identical, adding a second customer type to one service means duplicating the whole plan just to change one component.
Capability: Must help share select logic across separate plans
Say a business decides against putting customer type inside one component’s condition. Residential and commercial diverge in enough places that two separate plans are just easier to manage. That is a fair choice. But it cannot cost you duplicated logic where the two plans are genuinely identical. If both plans owe the exact same tax, calculated the exact same way, that logic needs to live in one place. A pricing module can hold just that one piece. Both plans point at it, instead of each writing its own copy. Change the tax rule once, in that one module, and both plans pick up the change on their next cycle. Nobody has to hand-edit two plans, and neither plan quietly falls out of sync with the other.
None of this is exotic engineering. It is just what is actually required to model the examples on this page correctly, for as long as they need to keep being billed.
How Billspree Helps
Every requirement above is real. Billspree is built to satisfy all of them — not as five unrelated features, but as one mechanism applied consistently. Here is each one, mapped to what actually does the work.
Adding new components
In Billspree, a business defines its own bill structure on a Pricing Template. A Template holds up to 50 Values and Components, named and ordered however the business needs. Nothing is fixed in advance. A new charge, a new tax, or a new fee is just a new entry on the Template — not a support ticket.
Defining output logic
Whatever gets added does not have to commit to being a plain number or a formula up front. Every component on a Pricing Template carries a Calculation Type. It is either Manual, a value entered directly, or Calculated, governed by a rule: Conditions and a Billing Formula. This is the exact mechanic behind Rate holding one flat number for the residential plan and a three-tier formula for the commercial plan. Same kind of component, different Calculation Type, chosen per plan.
Components referencing each other, and resolving to nothing when they should
Once those numbers exist, a rule in one component can reference any earlier component, by its Order. A tax can read straight off a specific charge instead of the whole bill. Billspree calls this mechanic Component Chaining. A Calculated component with no matching rule, or nothing to trigger it, does not error. It resolves to zero and moves on. This is exactly what lets a late fee sit dormant most cycles, without anyone writing a special case for it.
Varying logic by customer type
Customer-driven variation has two legitimate homes here, matching the two options from before. It can live inside one component’s Conditions, checking a Subscription Property like customer type, and picking a formula accordingly. Or it can live across two separate Pricing Modules, built on the same Template — one for Residential, one for Commercial — each with its own Rate. Plan A and Plan B, from the examples above, are exactly this: two Pricing Modules, each with Plan marked so a customer can actually subscribe to them.
Sharing select logic across separate plans
Sometimes two modules need to share something exactly, instead of duplicating it. That is what a Pricing Module built purely to be inherited from is for. A Tax Module holds just the tax rules. A Rate Card holds just the rate values. Neither is a complete plan on its own, and nobody subscribes to either one directly. Each exists only to be pointed at. Point both the Residential and Commercial modules at the same Tax Module. Update it once, and both modules pick up the change live, the next time each one bills. The two plans do not quietly drift apart because one got edited and the other didn’t.
Full detail on both mechanisms is in the docs: Pricing Template and Pricing Module.