What It Would Take to Hit 500K TX/Sec, and Why That's the Honest Answer
Capacity planning conversations have a predictable failure mode: someone names a big target number, and the answer that gets built is optimized for sounding capable of hitting it, not for being honest about whether it actually can. This is the opposite of that. A benchmark measured SupraScan's real sustained throughput, three concrete scaling levers were evaluated with honest multipliers instead of aspirational ones, and the combined answer, done as carefully as possible, still fell 25 times short of a 500,000 transaction per second target. The useful output of this exercise wasn't a bigger number. It was knowing exactly why that number wasn't reachable with this architecture, and what would actually be required if it mattered enough to pursue.
The baseline, and where the bottleneck actually was
A benchmark run measured roughly 110 to 118 transactions per second sustained, across ten running instances. The instinct when a number looks low is to assume the database is the constraint. It wasn't. In the same benchmark window, Postgres itself sat at 50 percent CPU idle, meaning it had considerable spare capacity at that load. The actual bottleneck was the RPC layer: 34 socket-hangup errors inside a 37-second window, with latency climbing past 600 milliseconds. The system wasn't write-constrained. It was constrained by how fast data could be safely pulled out of the chain node in the first place.
Three levers, evaluated without rounding up
Three concrete changes were assessed, each given a multiplier grounded in what it actually does rather than what would sound good in a roadmap slide.
Switching from a pull-based RPC pattern, roughly two RPC calls per block today, to a push-based WebSocket feed removes the single biggest blocker at the current scale: a thundering-herd effect on the RPC endpoint that gets worse as more instances are added, and which currently caps how many instances can even run productively. But this lever is explicitly a ceiling-remover, not a throughput multiplier on its own. It adds zero additional database write capacity by itself; it only clears the obstacle currently in front of scaling out further.
Sharding write traffic is the only one of the three levers that actually multiplies database capacity, because the current architecture writes through a single Postgres primary. Splitting into 8 to 16 shards was judged a plausible, though explicitly not linear, 8 to 16x increase in write ceiling. The honest caveats matter here: cross-shard queries, anything resembling a leaderboard spanning many wallets, get meaningfully harder once data is split this way, and a real, observed pattern of hot-shard skew, one specific address firing continuous automated self-transactions, actively eats into the theoretical gain by concentrating load unevenly across whichever shard that address lands on.
Replacing trigger or sync-based wallet counting with write-ahead-log-derived counters targets the hot-row contention problem directly, the same contention responsible for the multi-day lag incident described elsewhere in this series. Its honest impact is bounded: an estimated 20 to 50 percent reduction in per-transaction database work, explicitly not a throughput multiplier in its own right.
The math, done honestly, and the verdict it produces
Combining all three levers, removing the RPC bottleneck, applying an 8 to 16x sharding gain, and applying a 1.3 to 1.5x reduction from WAL-based counting, produces a combined estimate in the range of 2,000 to 20,000 transactions per second. Against the measured 118 TPS baseline, that's a genuinely significant 15 to 150x improvement, nothing to dismiss.
Measured against a 500,000 transaction per second target, even the optimistic end of that range falls roughly 25x short. That's the actual verdict: not reachable this way. Getting to 500,000 for real wouldn't mean tuning the current design harder. It would require a different architecture tier entirely: dozens to hundreds of shards rather than the 8 to 16 evaluated here, a move away from row-by-row ORM inserts with multiple dependent child-table writes per transaction toward bulk or columnar ingestion, since that per-transaction write pattern doesn't scale to that volume regardless of how many shards it's split across, and very likely a genuinely distributed database engine built for that scale, not a set of independently-sharded single-node Postgres instances glued together.
Why saying no was the right call
The easy version of this exercise ends with a roadmap slide showing a path to 500,000 TPS built out of optimistic rounding at each step. The honest version treats a target that large as an architecture-tier decision, a different system built differently from the ground up, not a tuning destination you inch toward by stacking incremental wins. The WAL-based counting work is still worth doing on its own terms, the hot-row contention it targets is real and worth fixing regardless. But it doesn't get oversold internally as a credible step toward a 500,000-tier system, because the math says plainly that it isn't one. Knowing the difference between a real, bounded improvement and a genuine step toward a stated target is most of what capacity planning actually is.