How We Built Our Escrow System (And What Went Wrong)
By Dave Kouri
When we started building BidTable, we assumed payments would be the easy part. Stripe exists. Stripe Connect exists specifically for marketplaces. How complicated could it be?
Turns out: pretty complicated.
The basic flow is straightforward. Client funds the project upfront, money sits in escrow, freelancer does the work, client approves, funds release. We had this working in about a week. The hard part was everything that happens in between.
The edge cases stack up fast
First problem we hit: what happens when a freelancer delivers work and the client just... disappears? Goes quiet, stops responding, doesn't approve or reject. We held $1,200 in limbo for three weeks on one of our early projects before we realized we needed a policy for this.
We now auto-release funds 5 business days after delivery if the client hasn't responded. That number came from looking at our support tickets and asking "what's the longest a reasonable client takes to review finished work." Most clients respond within 48 hours. Five days felt right.
Second problem: partial deliverables. A client posts a project for a logo plus brand guidelines. Freelancer delivers the logo on time but the guidelines are two weeks late. Does the client have to hold everything in escrow for the full project? This created real tension on a couple of projects.
We're still working on proper multi-milestone escrow. For now, our support team handles these manually, which doesn't scale.
Disputes
Dispute resolution is where we spent the most time. Our initial policy was basically "look at the project brief and the deliverables and make a judgment call." Which works when both sides are being reasonable. It doesn't work when a client is trying to get work for free by disputing everything.
We've since added a clearer framework: if the freelancer can demonstrate they delivered what was specified in the brief, the client bears the burden of proof for why it doesn't meet requirements. Vague complaints ("it just doesn't feel right") don't hold up. Specific complaints tied to specific brief requirements do.
We also track dispute rates per user. Anyone with a dispute rate above 15% gets reviewed manually before their next project can go live.
What we'd do differently
Honestly, we'd have built the milestone system from the start instead of trying to bolt it on later. The plumbing for it is significantly more complex than a single-payment escrow, and we underestimated that.
We'd also have built better tooling for our support team earlier. For the first six months, dispute resolution was mostly Slack messages and shared Google Docs. Not great.
If you're building a marketplace and thinking about payments: whatever your worst-case estimate is for edge cases, double it.