Somebody handed me a dashboard that took 20 to 30 seconds to load. Not because the server was slow. Because it was placing twelve thousand phone calls to a database to render one screen.
What I actually inherited
I didn’t write this one. This was a legacy internal application, originally built by a mix of contractors and junior developers, and I came in afterward to stabilize and maintain it. One user had roughly a thousand items sitting in their queue. The dashboard’s job was simple: show them all. The code that did it wasn’t.
One query ran first, pulling the list of all thousand items. Then, for every single one of those thousand, twelve separate queries fired off to pull the details needed to actually display it. No batching. No caching. No pagination anywhere in the picture, so the backend wasn’t even trying to hand back a manageable page at a time, it was handing back the entire thousand-item list in one shot, then rendering all thousand rows by hand on the frontend, with no real table underneath any of it.
A thousand items, times twelve queries each. Twelve thousand round trips to a database, for one person opening their inbox.
The fix that wasn’t clever
The fix wasn’t some elaborate caching layer or a rewrite. It was the word JOIN, a feature that’s been sitting in SQL since before either of us were writing code. Instead of one query to get the list and twelve more per row to get the details, a single query, structured correctly, could pull everything needed in one pass. I stood there staring at the query plan doing the mental math on how somebody got handed a computer science degree and managed to skip the one lecture that mattered most for exactly this situation. Twelve thousand queries became roughly three thousand.
Not a technique. A word that had been sitting in the manual the whole time, unused.
Why this happens, and why it’s not really about any one person
This is what a codebase looks like when a junior developer, fresh out of school, gets handed the keyboard with nobody around to say “hey, that’s not how you talk to a database.” Not malice. Nobody sat down and decided to write something this expensive on purpose. It’s what happens when “just get the data for this row” gets written once, works completely fine against five test records, and then quietly compounds into a disaster as the real data grows past whatever anyone tested against.
Why I still think about this one, years later
Here’s the part that’s actually stuck with me, watching Claude and Copilot both write code for me now, on projects I’m building myself, not inheriting from anyone. That exact pattern, loop over a list, fire off one query per item instead of one real query with a join, is still the default move an AI coding assistant reaches for unless you catch it. It looks completely reasonable in isolation. Every individual query is fine on its own. Nobody notices the actual shape of it until someone’s staring at a spinner for thirty seconds, wondering what’s wrong with their internet connection, when the truth is their internet connection was never the problem.
I didn’t invent the lesson that taught me to watch for this. I just happen to be the one who’s still checking for it, more than a decade later, in code that isn’t even mine to begin with this time either.