How to bill for storage using the weighted-sum metric
Last updated: June 29, 2026
The weighted sum metric charges for a resource based on both how much was held and how long it was held during the billing period. It suits storage billing, where a customer holding 100 GB for a full month should pay more than one holding the same 100 GB for a day. You send events as the stored quantity changes, and Lago weights each value by the time it was in effect.
Weighted sum charges are always billed in arrears. Pay in advance is not supported for this metric type, so plan your billing model around end-of-period invoicing.
How it works
The stored quantity holds steady between events and changes only when a new event arrives. Lago multiplies each quantity by the length of the interval it was in effect, sums those contributions, and normalizes to the full period. The result is a time-weighted quantity that the charge rate then prices.
For example, a customer holding 100 GB for 12 hours of a 30-day (720-hour) month gives a weighted quantity of 100 × (12 / 720) = 1.67 GB-months. At $50 per GB-month, that contributes about $83.50. The same logic scales to TB-month pricing through the rate.
The only native time unit is seconds, set with weighted_interval: seconds. Express your charge rate in per-second terms to match.
The recurring flag
When the metric is set to recurring, the last known quantity carries forward into the next period if no new event arrives. For storage this is usually correct: a customer who sends no new event still has data stored and should keep being billed at the last reported value. But it will keep billing at that value until the next event corrects it, so enable it deliberately and make sure your integration sends an event when stored volume actually goes to zero.
Choosing how to set it up
For almost all storage billing, use Option A.
Option A, native (recommended): configure weighted_interval: seconds and set the rate per second. Time-weighting is handled for you, with no extra event fields required.
Option B, custom expression for hour-based display: only if you specifically need usage shown in hour-based units, use a sum aggregation with a custom expression:
((event.properties.ended_at - event.timestamp) * event.properties.gb) / 3600
This requires every event to carry a start timestamp and an ended_at value, adding ingestion complexity. Hour-based granularity is not available as a native weighted_interval option, which is the only reason Option B exists.
This article reflects guidance drawn from customer case resolutions. It is not officially supported documentation and may not apply to all situations.