Stripe Connect looks simple in demos and complex in production. The tricky part is not charging cards, it is lifecycle handling when accounts, payouts, refunds, and compliance states change over time.
Core design choices
- Keep payment and payout states explicit in your own database.
- Treat webhook handlers as idempotent.
- Separate customer billing flow from provider payout flow.
- Make reconciliation a first-class background process.
What helped most
- A durable event table (
event_id,type,received_at,processed_at,status). - Retry-safe handlers using deterministic operation keys.
- Queue workers for non-blocking side effects.
- Monitoring for delayed payouts and mismatched transfer amounts.
Failure modes that usually appear
- Duplicate webhook deliveries causing duplicate state transitions.
- Connected accounts partially onboarded but still selected in checkout flow.
- Refund logic that does not mirror transfer reversals.
Production payment systems are mostly about safe state transitions and clear observability, not just API calls.