Skip to main content
Back to Blog
Payment Systems

Stripe Connect Architecture for Multi-Tenant SaaS Platforms

How to design a robust payment architecture for multi-tenant SaaS using Stripe Connect. Covers account types, fee structures, onboarding flows, and common pitfalls.

Ginquel Moreira

Senior Fullstack Developer & Fintech Specialist

10 min read

One of the most common architectural challenges in SaaS development is handling payments across multiple tenants. Your platform needs to collect payments from end users, take a platform fee, and route the remainder to the merchant or service provider. Stripe Connect is purpose-built for this, but choosing the wrong account type or fee model early on creates technical debt that is expensive to fix.

This post covers the key architectural decisions, based on real experience building multi-tenant payment systems.

The Three Stripe Connect Account Types

Stripe Connect offers three account types, each with different tradeoffs:

Standard Accounts

  • Merchants manage their own Stripe dashboard
  • Lowest platform liability
  • Best for marketplaces where sellers are established businesses
  • Limited branding control

Express Accounts

  • Stripe-hosted onboarding and dashboard
  • Good balance of control and simplicity
  • Best for platforms where merchants are individuals or small businesses
  • Moderate branding control

Custom Accounts

  • Full control over the user experience
  • Highest development effort
  • Best for platforms requiring white-label payment experiences
  • Full branding control, full liability

Recommendation: Start with Express unless you have a specific reason not to. You can always migrate later, and Express handles KYC/KYB verification out of the box.

Fee Architecture

The fee model determines how money flows through your platform. There are two primary patterns:

Direct Charges

The charge is created on the connected account. The platform takes an application fee.

const paymentIntent = await stripe.paymentIntents.create({
  amount: 10000, // $100.00
  currency: 'eur',
  application_fee_amount: 1500, // $15.00 platform fee
  transfer_data: {
    destination: connectedAccountId,
  },
});

Best for: Marketplaces where the merchant is the primary party (e.g., Upwork, Airbnb).

Destination Charges

The charge is created on the platform account and funds are transferred to the connected account.

const paymentIntent = await stripe.paymentIntents.create({
  amount: 10000,
  currency: 'eur',
  transfer_data: {
    destination: connectedAccountId,
  },
}, {
  stripeAccount: undefined, // Charge on platform
});

Best for: Platforms where the platform is the primary brand (e.g., food delivery, SaaS with sub-accounts).

Onboarding Flow Design

A smooth onboarding flow is critical for merchant conversion. Here is the pattern I use:

  1. Create connected account when merchant signs up (minimal data)
  2. Generate account link for Stripe-hosted onboarding
  3. Handle return URL to check verification status
  4. Listen for webhooks to track onboarding completion
// Step 1: Create account
const account = await stripe.accounts.create({
  type: 'express',
  country: 'PT',
  email: merchant.email,
  capabilities: {
    card_payments: { requested: true },
    transfers: { requested: true },
  },
});

// Step 2: Generate onboarding link
const accountLink = await stripe.accountLinks.create({
  account: account.id,
  refresh_url: `${baseUrl}/onboarding/refresh`,
  return_url: `${baseUrl}/onboarding/complete`,
  type: 'account_onboarding',
});

Webhook Architecture

Webhooks are the backbone of any Stripe integration. For multi-tenant platforms, you need to handle webhooks from both your platform account and connected accounts.

Key webhooks to monitor:

  • account.updated — Onboarding status changes
  • payment_intent.succeeded — Successful payments
  • payment_intent.payment_failed — Failed payments
  • transfer.created — Money movement to connected accounts
  • payout.paid — Money sent to merchant bank accounts

Critical pattern: Always use idempotency keys and verify webhook signatures. Process webhooks idempotently — the same event may arrive multiple times.

Common Pitfalls

1. Currency Mismatch

If your platform operates in EUR but a connected account is in GBP, Stripe will handle conversion, but fees apply. Design your data model to track currencies per tenant.

2. Negative Balances

When refunds occur, the connected account balance may go negative. Your platform is liable. Implement balance checks before processing refunds.

3. KYC Deadlines

Stripe requires verification within a certain timeframe. If a merchant does not complete onboarding, their account gets restricted. Send proactive reminders.

4. Tax Reporting

In the EU, you may need to report payments to connected accounts. Stripe Tax can help, but the responsibility is yours.

Database Schema Design

For the multi-tenant payment layer, I recommend this minimal schema:

  • tenants — Platform customers (merchants)
  • stripe_accounts — One-to-one with tenants, stores stripe_account_id and onboarding status
  • transactions — Every payment intent, linked to tenant
  • payouts — Payout records per tenant
  • webhook_events — Idempotency log for processed webhooks

Keep the Stripe account ID as the foreign key in your transactions table. Never store sensitive payment data — let Stripe handle PCI compliance.

Testing Strategy

Stripe provides excellent test mode tooling:

  • Use test API keys for all development
  • Simulate onboarding with test account numbers
  • Trigger webhooks via Stripe CLI: stripe trigger payment_intent.succeeded
  • Test edge cases: declined cards, 3D Secure, insufficient funds

Conclusion

Stripe Connect is powerful but requires upfront architectural decisions that are difficult to change later. Choose the right account type, fee model, and onboarding flow based on your specific business model. Invest in webhook reliability early — it pays dividends as your platform scales.

For help designing your multi-tenant payment architecture, reach out to discuss your platform requirements.

StripeSaaSPaymentsArchitectureNode.js

About Ginquel Moreira

Senior Fullstack Developer & Fintech Specialist

Senior fullstack developer specializing in enterprise fintech applications. Building production-grade systems with Java Spring Boot, Angular, React, and modern cloud architecture. Based in Portugal, serving clients worldwide.

Need Expert Fintech Development?

From architecture to deployment, I help companies build reliable fintech platforms. Let's discuss your project.

Start a Conversation