A compliance reviewer told me the account page took about three seconds to open. On my machine it was instant.
The difference was the test data. My fixture account had a handful of transactions. Hers had years of them.
The balance was computed on read: sum every ledger entry for that user, every time the page loaded. It was correct. It was honest too. And it got slower with every payment the account had ever made.
The endpoint was not slow in general. It was slow in proportion to how much the customer had used it. The accounts that mattered most were the worst ones to work with, and those were exactly the accounts reviewers opened all day.
The expensive part: nobody filed it as a bug for months. It didn't read like a defect, it read like a heavy page. People learned to wait, and the moderation queue quietly absorbed the delay.
Now I treat a balance as stored state instead of a query. Entries append and the stored balance moves with them inside the same transaction. A separate job recomputes from history to prove the stored number still matches. Read paths stay off the past.
I also stopped benchmarking against fresh fixtures. If an endpoint touches a user's history, I test it with the oldest, busiest account in the system, the one that will exist in two years rather than the one created five minutes ago.
I write more about ledger and reconciliation trade-offs here: https://polycratia.com/c/719c4fe4
Worth knowing where your data grows fastest per user, and whether there's still a read path that walks it end to end...