Multi-tenant SaaS with Billing
Tenant-isolated SaaS platform with usage-based Stripe billing
Overview
What this is
A multi-tenant SaaS platform where organizations can switch between workspaces, data is isolated per tenant at the database level, and billing enforces usage limits automatically across three subscription tiers.
Problem
Why it needed building
Multi-tenant systems fail in two classic ways: data leaking across tenant boundaries, and billing state drifting out of sync with what a customer actually has access to (especially around failed payments and plan changes).
Solution
How it works
Clerk handles organization switching and identity, while row-level data isolation in PostgreSQL guarantees one tenant can never read another's data — enforced at the database layer, not just in application code. Stripe subscription webhooks (created, updated, cancelled, past-due) are processed with idempotency keys, and a failed payment automatically triggers plan downgrade enforcement at the API layer.
Architecture
How it's put together
- →Row-level security in PostgreSQL for per-tenant data isolation, not just query-level filtering
- →Clerk organization switching for multi-workspace identity management
- →Three billing tiers with usage-based limits enforced at the API layer, not just checked in the UI
- →Idempotent Stripe webhook handlers covering the full subscription lifecycle
Challenges
The hard part
Keeping billing state consistent with actual access required treating 'payment failed' as a first-class state machine transition, not an afterthought — a downgrade has to be enforced immediately and automatically, not caught later by a support ticket.
Trade-offs
What I gave up on purpose
Enforcing usage limits at the API layer (rather than trusting the frontend) adds a check to every relevant request, but it's the only way to guarantee a downgraded tenant can't keep exceeding their plan through direct API calls.
Performance
What changed, measurably
Billing state inconsistencies reduced to zero through idempotent webhook handling and automated downgrade enforcement on payment failure.
Next
What I'd build next
Add self-serve plan comparison and proration preview before a tenant confirms an upgrade or downgrade.