McLeod Bob-Manuel
All writing

What scaling a platform to $20M in transaction volume in a year taught me

Engineering lessons from growing a stablecoin wallet platform from a proof of concept to 6,000+ wallets and nearly $20M in volume across seven chains.

Sotonye McLeod Bob-Manuel5 min read

In early 2025, the crypto side of the business ran on somebody else’s infrastructure. We paid a provider around $3,000 a month for wallets and transfers, and whenever a customer asked for something new, the honest answer was “let me check what they support.”

A year later, the same product had moved nearly $20M across more than 6,000 wallets on seven blockchains, and every line of it ran on infrastructure we had built ourselves.

The hard part wasn’t the blockchain code. It was everything around it: knowing a balance is right, surviving providers that go quiet, and making sure a customer’s integration never broke while we changed the ground under it. This is the first of two posts on that year. This one is about scale. The next is about owning a product end to end.

Buy, until the vendor’s roadmap becomes your ceiling

I’m not a “build everything” person. For most infrastructure, buying is the right call.

What changed my mind was looking at what we kept saying no to: payouts on a chain the provider didn’t support, treasury flows in a stablecoin they hadn’t added, a card product funded from crypto balances. That wasn’t a backlog. It was a business we were turning away.

So I didn’t write a proposal. I built a small wallet service that could create addresses, see deposits and send funds on one chain, and ran it next to the provider. It was rough. It also settled the argument faster than any document could have, because the question stopped being “should we?” and became “how soon can this carry real money?”

The ledger is the product

The first real lesson came early, and it reshaped everything after it.

A blockchain will tell you what happened on the blockchain. A webhook will tell you what a provider thinks happened. Neither of them tells you what your customer’s balance is. That’s your job, and if you let any external signal write a balance directly, sooner or later two of those signals will disagree and you won’t know which one to believe.

We made one rule: a balance is only real if a ledger entry explains it. Chains, providers and partners are inputs. The ledger is the truth. It sounds obvious written down. It is surprisingly easy to drift away from when you are shipping fast.

Assume every message arrives twice

Events from blockchains arrive late, out of order, and more than once. Customers retry requests when their network flickers. Your own workers retry when a dependency times out.

You can’t stop any of this, so stop trying. Give every operation a natural identity, store it in the same write that moves the money, and a duplicate becomes a no-op instead of an incident. For an on-chain transfer, the identity is already there: the network, the transaction, and the transfer’s position inside it. For a customer request, it’s the idempotency key they send.

Once we did this everywhere, a whole category of 2am questions simply went away.

Reconciliation is not a safety net

Our first approach to catching missed deposits was the obvious one. Listen for events, and every so often scan every wallet on every chain to make sure nothing slipped through.

It worked at a few hundred wallets. At a few thousand it became a problem. We were hammering external RPC providers around the clock, and when one of them slowed down, the scans fell behind exactly when we most needed them.

Deposits are de-duplicated and written to the ledger once; a scheduled reconciler then reads the ledger first, checks only the wallets that should have changed against the chain, and repairs and alerts on anything that does not match.
Record every deposit once on the way in, then prove it again later, starting from what you already know.

The fix was to turn the scan around. Instead of asking the chain about everything, the reconciler starts from the ledger, works out which wallets could plausibly have changed, and asks the chain about those. Anything that doesn’t match gets repaired and someone gets told.

That cut our external scan load by 87% across more than 5,400 monitored wallets, and coverage got better, not worse, because the checks we kept were the ones that mattered. The bigger lesson was in how I thought about it afterwards. Reconciliation isn’t a backup for the real system. It is the real system, and it deserves the same design care as the happy path.

Every provider will let you down eventually

Seven chains means seven sets of RPC providers, indexers and data feeds, and on any given week at least one of them is having a bad day. Rate limits appear without warning. A provider returns stale data with total confidence.

The pattern that saved us was dull and consistent: every external call has a timeout, a fallback and an alert, and no single provider is ever the only way to know something. It’s not clever engineering. It is the difference between a slow afternoon and a customer-facing outage.

Docs are part of the platform

This one surprised me most. I wrote the documentation myself, 267 code examples in the end, and we kept SDKs in five languages, including the public PHP SDK. I thought of it as onboarding work.

Then we needed to change how authentication worked. We moved every customer from shared account credentials to per-team API keys, IP allowlists and passkeys. On a payments platform that is a frightening migration, because a broken integration means someone’s payouts stop.

It went through with zero downtime, and the reason was the docs. Every example and every SDK was ours, so we updated all of them first, ran the old and new credentials side by side, and only switched the old path off once nobody was using it. If you own the examples, you can change the system underneath them.

What I’d tell a team starting today

Write down your rules before you need them. “The ledger is the truth” and “every operation is idempotent” prevented more incidents for us than any test suite did.

Build for the second product, not the first. The ledger and the background workers we built for wallets are what made swaps, cross-chain payouts and card funding cheap to add later.

And measure what customers actually feel. Nobody ever asked us about throughput. They asked whether their balance was right and how long a payout took.

In part two, I’ll write about the feature that answered that second question, and what owning it end to end taught me about product.

  • Engineering
  • Scaling
  • Payments
  • Stablecoins