Engineering Case Study

Evolving from Direct Payments to an Internal Financial Platform

How an initial direct Stripe payment flow evolved into an internal financial platform supporting wallets, escrow, delayed settlement, disputes, and Stripe Connect payouts.

18 min read·Published July 2026

Overview

The platform originally processed reservations and event payments by creating a Stripe PaymentIntent for every transaction.

That approach satisfied the initial business requirements, but as the platform evolved, new financial workflows began to emerge.

Users needed wallet top-ups.

Reservations required delayed settlement.

Managers needed withdrawals.

Payments could enter disputes before funds were released.

Campaigns introduced additional financial workflows.

Manager earnings required delayed settlement before becoming available for withdrawal.

Disputes introduced new transaction lifecycles that extended beyond a simple payment.

Each new requirement increased the amount of business logic coupled directly to Stripe.

Rather than continuing to expand the payment flow, the platform introduced an internal financial layer responsible for modeling balances, settlements, and transaction history, while Stripe became responsible only for moving money into and out of the platform.

The Problem

Direct payment processing works well when every payment immediately reaches its final destination.

Marketplace platforms rarely behave that way.

Funds may need to be:

  • held before settlement
  • released after a dispute window
  • refunded
  • forfeited
  • transferred to connected accounts
  • withdrawn to external bank accounts

Attempting to model those workflows directly around PaymentIntents quickly scattered financial logic throughout the application.

The system needed a single source of truth for every monetary event.

Architecture

Stripe
Wallet Top-ups
Internal Wallet
Double-Entry Ledger
Escrow
Campaign Fees

Every marketplace financial operation now passes through the same internal platform regardless of its origin.

Bookings, events, campaigns, subscriptions, refunds, and withdrawals all share the same financial primitives.

Engineering Decisions

Decision 01
Separate payment processing from financial state

Stripe became responsible for moving money, while the platform became responsible for modeling ownership, balances, settlements, and financial history.

This reduced coupling between business logic and the payment provider while creating a consistent financial model across every feature.

Decision 02
Model financial workflows as domain concepts

Wallets, escrow, withdrawals, disputes, and settlements were modeled as first-class domain concepts rather than side effects of payment processing.

This allowed complex financial workflows to evolve independently from Stripe's APIs.

Challenges

Designing an internal financial platform introduced several engineering challenges.

Balance mutations had to remain atomic under concurrent requests.

Every monetary event needed to be fully auditable.

Escrow required delayed settlement without blocking API requests.

Withdrawals needed approval workflows, Stripe Connect integration, and protection against duplicate payouts.

Each of these concerns was solved independently while sharing the same underlying financial primitives.

Outcome

The resulting architecture provides a single financial platform used across the entire application.

Wallets act as the source of truth for balances.

Escrow manages delayed settlement.

Stripe Connect handles external payouts.

Background workers process long-running financial operations.

Rather than extending direct payment flows whenever a new marketplace requirement appeared, the platform now evolves by composing well-defined financial building blocks that remain reusable across reservations, events, campaigns, disputes, and withdrawals.