Skip to main content

Configuration fields

FieldDescriptionRequiredDefault
valuePercentage to discount (e.g., 20 = 20%)Yes
max_per_periodDollar cap on discount within a cadence windowNoUnlimited
cadenceCap refresh period (P1M, P3M, P1Y, etc.)NoNone (falls back to billing cadence)
max_lifetimeCumulative dollar cap on discount across all periodsNoUnlimited
labelDisplay label on invoiceNo
orderExecution order when stacking multiple discountsNo

Validation rules

RuleValidInvalid
value between 0 and 10020−5, 150
max_per_period non-negative if set500−1
max_lifetime non-negative if set5000−1
Caps are dollar amounts, not percentagesmax_per_period=100 means a $100 capNot a 100% cap
max_per_period requires a period referenceWith cadence or a billing cadenceNeither means invalid

Core calculation

  1. Calculate the gross bill amount, after quantity discounts, the pricing model, and commitments.
  2. Apply the percentage: discount = value% × gross_amount.
  3. Cap the discount, if configured: discount = min(discount, remaining_period_cap, remaining_lifetime).
  4. Subtract: invoice_amount = gross_amount − discount, floored at $0.

Cadence resolution order for max_per_period

  1. cadence, if set.
  2. Billing cadence, as a fallback.
  3. If neither is available, max_per_period is invalid.

Cadence relationships

RelationshipExampleBehavior
Cadence = billingMonthly/monthlyEach period independent
Cadence larger than billingQuarterly/monthlyThree months grouped; cap applies to the quarterly total
Cadence smaller than billingWeekly/monthlyAbout four cap windows per billing period
No cadenceEach billing period independent

Proportional distribution formula (cadence grouping)

Step 1: Group periods into cadence windows
Step 2: group_discount = value% × sum(all period amounts in window)
Step 3: Apply max_per_period cap to the group total (if set)
Step 4: Distribute back: period_share = group_discount × (period_amount / sum)
Step 5: Remainder cents go to the last period in the window

Cap summary

LevelFieldStateRefreshes
Per-periodmax_per_period + optional cadenceWithin windowAt cadence boundary
Lifetimemax_lifetimeForeverNever

Order of operations (full calculation stack)

1. Raw usage
2. Quantity discount: adjusted quantity
3. Minimum quantity: effective quantity
4. Pricing model: gross amount
5. Minimum spend: max(gross, min spend)
6. Fixed discount: amount minus fixed (floored at $0)
7. Percent discount: amount × (1 − value%)
8. Final total

Natural ordering when stacking discount types

StepDiscount typeReduces
1Quantity discountUnits
2Fixed discountDollars (flat)
3Percent discountRemainder (%)
Multiple percent discounts compound rather than add: 20% + 10% = 1 − (0.8 × 0.9) = 28%, not 30%. For uncapped percents, order doesn’t change the result; with caps, order matters.

Invoice presentation

The discount appears as a line item on the invoice using the configured label. Each period produces a breakdown record tracking: amounts before and after, discount applied, raw discount (pre-cap), percentage, period and lifetime cap remaining, and whether any cap was hit.

Risks and edge cases

ScenarioHandling
100% discount without a capCustomer pays $0 indefinitely; confirm this is intentional
Lifetime cap exhaustionNot visible to the customer in advance unless entitlement tracking is separately surfaced

Glossary

TermDefinition
Percent discountPercentage deduction from gross bill amount; stateless
Gross amountBill total after quantity discount, pricing model, and commitments — before percent or fixed discounts
BreakpointBill amount where the per-period cap starts to bite: max_per_period ÷ (value/100)
CadenceRefresh frequency for max_per_period; groups billing periods into cap windows
Cadence windowTime span covered by one max_per_period cycle
Proportional distributionGroup discount allocated to periods proportional to their gross amounts
Degressive discountDeclining effective rate when caps limit the dollar discount on larger bills
CompoundingTwo sequential percent discounts multiply: 20% + 10% = 28%, not 30%

Out of scope / deferred

FeatureDescription
max_per_eventPer-event dollar cap; requires event-level data
Event breakdown integrationPer-event discount tracking within a billing period
Three-level cap stackmax_per_event + max_per_period + max_lifetime; only two levels currently
Percentage-based capsCurrent caps are dollar amounts only, not “at most 50% off” style caps
Cross-product discountsA shared percent discount across multiple products
Discount validity / expiryIndependent start and end dates on the discount itself

Open questions

#QuestionStatus
1Should discount validity be a separate start/end date, or follow the line item’s lifecycle?Needs clarification
2If discount duration is shorter than the subscription, how is it applied across product and quantity types?Needs clarification
3When discount cadence is larger than billing cadence, is the discount applied at the end of the discount cadence or the end of the billing period?Needs eng validation
4When a cadence-distributed discount is capped, are there retrospective adjustments as later periods change the proportional distribution?Needs eng validation
(Placeholder: status of open questions should be confirmed before this doc is published externally.)