Skip to content
All posts

Stripe Connect: the playbook we wish we had

Five years of shipping Stripe Connect — marketplaces, payouts, dispute handling, and the edges that turn a working demo into a robust production system.

Shubham Somani 3 min read

If you’re building a marketplace and someone tells you to “just use Stripe Connect,” they’re not wrong. But the gap between a working Connect demo and a robust production system is bigger than it looks.

Here’s what we’ve learned from shipping Connect across gaming, hospitality, fintech, and golf.

Pick your account type once. Live with it.

Connect offers three account types: Standard, Express, and Custom. The choice has compound implications.

StandardExpressCustom
Onboarding UIStripe’sStripe’s (branded)Yours
KYC/AML responsibilityStripeStripeYou
Dashboard for connected accountsFull StripeLimitedNone
BrandingStripe’sYours + Stripe’sFully yours
Implementation costLowestMediumHighest

For 90% of marketplaces, Express is the right answer. Standard is fine if you don’t mind Stripe being the primary brand of the payments experience. Custom is rarely worth the engineering cost.

Webhooks are not optional. Idempotency is not optional.

You will get the same webhook delivered more than once. Stripe is explicit about this. Your handler must be idempotent.

Two patterns that work:

  1. Store the event ID before processing. Wrap the handler in a unique-key insert against an event_id column. If the insert fails (duplicate), short-circuit.
  2. Process at-least-once, design downstream consumers to be idempotent. Useful if you’re already on a queue-based architecture.
async function handlePaymentSucceeded(event: Stripe.Event) {
  const inserted = await db
    .insert(stripeEventsTable)
    .values({ id: event.id, type: event.type })
    .onConflictDoNothing()
    .returning();
 
  if (inserted.length === 0) {
    return;
  }
 
  await fulfillOrder(event.data.object as Stripe.PaymentIntent);
}

Reconciliation is the boring superpower

Every night, run a job that reconciles your DB against Stripe. Pull all charges from the previous day via the Stripe API, check that each one has a matching record in your DB, and alert on mismatches.

You will be amazed how many bugs this catches that webhooks alone do not — race conditions, missed retries, manual refunds someone did via the Stripe dashboard.

Disputes and chargebacks: have a runbook

A chargeback comes in. You have 7 days to respond with evidence. Who:

  • Gets the notification?
  • Pulls the evidence (order details, shipping confirmation, IP address, communication logs)?
  • Submits the response to Stripe?
  • Updates the customer record in your CRM?

Write that runbook before your first dispute, not after.

Connected account capability changes

In Express and Custom, connected accounts can have their capabilities restricted at any time — Stripe might require additional info, or a country’s regulation might change. Your code must handle:

  • An account that was able to receive payouts yesterday and isn’t today
  • Re-verification requirements (you’ll get a webhook)
  • Capabilities that are “pending” — somewhere between active and inactive

Build the UI for “your account needs attention” before you launch. It will save you a chaotic support cycle.

Tax: use Stripe Tax

Don’t roll your own. The complexity of marketplace tax across jurisdictions is genuinely staggering, and Stripe Tax handles it for a small percentage. Worth every basis point.

The minimum viable production setup

If you’re starting Stripe Connect today, here’s what we’d ship in week one:

  • Express accounts
  • One product / one currency to start
  • Webhook handler with idempotency from line one
  • Reconciliation job (nightly, alerting to Slack)
  • A dispute runbook in your team wiki
  • A “your account needs attention” page

Add Stripe Tax in week two. Add real-time payout scheduling in month two. Don’t try to ship everything on day one.


Stripe Connect is one of the best-engineered APIs in production today. It rewards taking time to read the docs carefully. If you’d like a second pair of eyes on your Connect integration, say hi.