How I Built a Multi-Tenant SaaS With Stripe Connect
Building a marketplace infrastructure is one of the most complex challenges in SaaS. You're not just taking payments; you're routing them, splitting them, and managing compliance for thousands of sub-merchants.
In this deep dive, I'll show you how I architected a payment system handling $50K+ monthly volume using Stripe Connect.
The Challenge
We needed a platform where:
- Customers pay for services.
- Service Providers (our users) get paid instantly.
- The Platform (us) takes a commission fee.
- Everything happens transparently and compliantly.
Handling money for others requires strict compliance (KYC/KYB). Never hold funds in your own bank account if you can avoid it. Stripe Connect solves this.
Architecture Overview
I chose Stripe Connect Custom Accounts for complete control over the onboarding UI.
// lib/stripe.ts
import Stripe from 'stripe';
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2023-10-16',
appInfo: {
name: 'MySaaS Platform',
version: '1.0.0'
}
});The Split Payment Flow
When a payment occurs, we don't just charge the card. We create a PaymentIntent that automatically routes funds to the connected account.
const paymentIntent = await stripe.paymentIntents.create({
amount: 5000, // $50.00
currency: 'usd',
automatic_payment_methods: { enabled: true },
application_fee_amount: 500, // We keep $5.00 (10%)
transfer_data: {
destination: connectedAccountId, // The Service Provider's ID
},
});Secure Onboarding with Webhooks
The most critical part is keeping account status in sync. Users might start onboarding, drop off, or get flagged for fraud.
We use webhooks to listen for account.updated:
export async function handleWebhook(event) {
switch (event.type) {
case 'account.updated':
const account = event.data.object;
await db.user.update({
where: { stripeAccountId: account.id },
data: {
payoutsEnabled: account.payouts_enabled,
chargesEnabled: account.charges_enabled,
}
});
break;
// Handle other events
}
}Handling Payouts
Funds accumulate in the connected account's Stripe balance. We configured automatic daily payouts to their bank accounts, reducing our liability.
| Feature | Custom Accounts | Express Accounts | Standard Accounts |
|---|---|---|---|
| Whitelabel UI | ✅ Yes | ❌ No | ❌ No |
| Global Reach | ✅ Yes | ✅ Yes | ✅ Yes |
| Dev Effort | 🔥 High | ⚡ Medium | 🟢 Low |
Results
After deploying this architecture:
- Onboarding Time: Reduced from 3 days to 5 minutes.
- Support Tickets: Dropped by 60% due to automated status transparency.
- Volume: Successfully scaled to $50K+ MRR without code changes.
Need help architecting your Stripe integration? Get in touch for a consultation.