Understanding Usage-Based Billing¶
In the world of cloud computing, usage-based billing is a pricing model where customers are charged based on their usage of a service. I quite like this model because it's fair. You pay for what you use, no more, no less. Let's explore this with a practical example.
Suppose you're a cloud provider charging customers for the amount of storage they use. Sounds simple? But what happens when:
- Usage changes multiple times during the month
- Early cancellation, what is fair to charge?
- Storage buckets can be created and deleted at any time
A practical example¶
In this completely hypothetical example, let's explore how to calculate a bill for a cloud storage service that charges $0.020 per GB per month. Let's follow a customer's usage pattern for a single bucket:
Think of "Storage Usage" as an event that causes a change, like uploading or deleting files, where we can calculate the usage at that point in time. Here's a simplified timeline:
Date & Time | Storage Usage |
---|---|
Start of month | 468 GB |
Feb 3, 7:00 PM | 502 GB |
Feb 9, 1:00 PM | 570 GB |
Feb 9, 3:00 PM | 602 GB |
Feb 18, 11:00 AM | 604 GB |
Feb 22, 12:00 PM | Account cancelled |
Feb 28, 11:59 PM | End of month |
How to calculate a fair bill?
Time-weighted average usage¶
The key is calculating a time-weighted average of usage. For this example, let's use hour as our time unit to keep thing ssimple. Note, when dealing with frequent changes, you'll want to use minutes or even seconds.
Calcualte for a full month first, then adjust for early cancellation.
-
Break down usage into time periods (for all of February assuming 28 days):
- 468 GB for 67 hours
- 502 GB for 138 hours
- 570 GB for 2 hours
- 602 GB for 212 hours
- 604 GB for 253 hours (until end of month)
-
Calculate GB-hours for each period:
- 468 × 67 = 31,356
- 502 × 138 = 69,276
- 570 × 2 = 1,140
- 602 × 212 = 127,624
- 604 × 253 = 152,812
-
Sum up the GB-hours and divide by total hours:
- Total GB-hours: 382,208
- Total hours in February: 672
- Average GB: 382,208 ÷ 672 = 568.76 GB
Early cancellation
Now, if the customer cancels on February 22 at noon, the calculation changes:
- We only count hours until cancellation (516 instead of 672)
- The last period becomes shorter (97 hours instead of 253)
- This gives a different average: 287,984 ÷ 516 = 558.11 GB
The beauty of this approach is that it automatically adjusts to any time period while maintaining fair billing based on actual usage patterns.
-
Calculate the bill for both scenarios:
Full month (through February 28):
- Average GB = 568.76 GB (calculated from all 672 hours)
- Daily rate = $0.020 ÷ 28 = $0.000714 per GB per day
- Days used = 28
- Final bill = 568.76 GB × $0.000714 × 28 = $11.38
Partial month (cancelled February 22 at noon):
- Average GB = 558.11 GB (calculated from 516 hours until cancellation)
- Daily rate = $0.020 ÷ 28 = $0.000714 per GB per day
- Days used = 21.5
- Final bill = 558.11 GB × $0.000714 × 21.5 = $8.57
Note, the average GB differs between scenarios because we're only considering usage up until the cancellation time in the partial month case.
Generalize¶
bill = (
# First, calculate the weighted units
(Σ(units_i × hours_i) ÷ total_hours)
# Then, get the daily rate
× (rate_per_month ÷ days_in_month)
# Finally, multiply by days used
× days_used
)
The formula can be broken down into three parts (using our February example):
-
Time-weighted average usage: sum(units × hours) ÷ total_hours
= 382,208 GB-hours ÷ 672 hours = 568.76 GB
This represents average usage accounting for all changes during the month
-
Daily rate: rate_per_month ÷ days_in_month
= $0.020 ÷ 28 = $0.000714 per GB per day
This converts monthly rate into a daily rate
-
Days used (proration factor)
- Full month: 28 days
- If cancelled Feb 22 at noon: 21.5 days
- This adjusts bill for partial month usage
Putting it all together:
- Full month: 568.76 GB × $0.000714 × 28 = $11.38
- Partial month: 558.11 GB × $0.000714 × 21.5 = $8.57
Bonus, for fun I built a simple Go package (mfridman/billing) to calculate this:
Early cancellation (or deletion of resources)¶
One of the most common billing scenarios is when customers cancel their service mid-month or delete resources before the end of the billing period. This can complicate billing calculations. The above formula should handle this because:
- The
total_hours
in the denominator only counts hours up until cancellation - The
days_used
term prorates the monthly rate appropriately - The weighted average usage only considers the actual usage period
For example, if a customer cancels on February 22 at noon:
- Instead of using all 672 hours in February,
total_hours
would be 516 (up until cancellation) days_used
would be 21.5 instead of 28- Usage after cancellation time is completely ignored in the calculation
This ensures customers only pay for what they actually used, both in terms of:
- Time (through prorated days)
- Resource consumption (through time-weighted average usage)
Useful¶
-
Track usage changes with precise timestamps
- Storing raw usage data at the highest practical resolution
-
Use consistent time zones!
- Store all timestamps in UTC internally
- Convert to local time only for display purposes
- Be explicit about time zones in customer-facing reports
-
Round final bills appropriately (typically to nearest cent)
- Provide detailed usage reports whenever possible
Lastly, make sure the billing system is not just accurate, but also understandable to customers.