All packsSaaS Billing + Tax CoreSolve
stripe seat based billing prorate seats add remove
Adding seats now, removing them at renewal
Seat increases prorate immediately; seat decreases must wait for period end -- refunding mid-cycle desyncs billing from the entitlements it's supposed to gate (D11).
What goes wrong
Seat count changes need the same asymmetric handling as plan changes: adding a seat mid-cycle should bill the prorated difference now, but removing a seat mid-cycle should not refund immediately -- the team already used those seats. Code that treats seat add and seat remove symmetrically either fails to charge for the seats actually used, or issues refunds the business didn't intend to give.
Why agents get it wrong
Seats look like a simple quantity field on a subscription item, so it's tempting to write one updateSeats() function that always calls the same Stripe update with the new quantity -- the asymmetry (immediate for increases, scheduled for decreases) isn't visible from the Stripe API shape itself, only from the architecture decision that says which direction gets which treatment.
What SaaS Billing + Tax Core pre-decides
D11 pins seat increases to the same immediate-update, always_invoice path as an upgrade, and seat decreases to the same scheduled-at-period-end path as a downgrade, reusing D10's existing-schedule rule so a decrease never creates a second schedule. Decreases below the currently occupied seat count, and increases above a plan's maxSeats, are rejected before any Stripe call runs -- billing must not desync from entitlements.
Source: ARCHITECTURE.md D11