Should we build billing ourselves or buy it?

Buy it, unless your pricing is unusual enough that no vendor models it.

What decides it

FactorBuild wins whenBuy wins when
Pricing modelFlat per-seatUsage-based with proration
ComplianceOne countryTax in several
TeamBilling is the productBilling is a line item

Proration is where in-house billing usually goes wrong. A plan change mid-cycle has to answer three questions at once:

ts
function prorate(from: Plan, to: Plan, at: Date) {  const remaining = daysLeft(at) / daysInCycle(at)  const credit = from.price * remaining  const charge = to.price * remaining  return charge - credit}

That looks complete and is not. It ignores trials, refunds, currency, and the case where to.price is lower.