
Spent the last week in my console fixing every billing edge case that isn't stripe checkout itself. No new features. No marketing. The change-log reads like a maintenance log:
Context: BuildBase is a multi-tenant SaaS backend I'm building. My customers create orgs inside my console and each org has its own subscription. Each edge case above came out of either dogfooding across our own products or watching signup-to-activation drop-off patterns.
Lesson I'm re-learning: Stripe checkout is maybe 10% of "billing." The other 90% is UI state, org scoping, deduplication, empty states, and handling every combination of (trial / active / past_due / canceled / no plan) x (owner / member / internal admin). None of it shows up on a landing page. All of it prevents support tickets.
Still $0 MRR from external customers. This week's work isn't going to change that on its own. But now the console doesn't look broken when a fresh signup lands in it with no plan yet, and that's the thing that was quietly killing my activation.
How are you handling the "signed up but no active plan" state? Full paywall, read-only preview, or something in between? Still iterating on that one myself.
This is a good reminder that “billing integration” and “billing system” are two very different things.
The org-scoping + duplicate-subscription cases especially caught my attention. Those bugs are dangerous because the happy path can work perfectly while the system is still capable of charging or exposing billing state for the wrong tenant.
I’ve started thinking about billing less as a checkout flow and more as a state machine: identity → subscription state → payment state → permissions → UI state.
The “signed up but no active plan” state is interesting too. I’d probably lean toward a limited read-only experience rather than a hard paywall, because it gives the user something to understand before asking them to pay.