How much of "it's slow" is actually a database problem
Most performance complaints trace back to the same place: how the app talks to its data.
When a client tells us "the app feels slow," we don't start by profiling the frontend. We start by opening the query logs. Nine times out of ten, that's where the story is.
Slowness gets blamed on everything except its actual cause. The framework is bloated. The server needs more RAM. The frontend bundle is too big. All of these can be true and still be irrelevant, because the real bottleneck is a query that scans a million rows to return ten, running fifty times on a single page load.
The pattern is almost always the same: an N+1 query hiding inside an innocent-looking loop, a missing index on a column that used to be small, or a query that joins five tables when it needs two. None of these show up in a stack trace. They show up as a vague, diffuse sense that "everything" is slow, which is exactly the symptom that sends people chasing the wrong fix.
The fix is rarely exotic. Add the index. Batch the fetch. Cache the thing that doesn't change every request. What's hard isn't the technique, it's noticing where to apply it, because the database doesn't complain loudly when it's struggling. It just quietly gets slower, month over month, until "slow" is the new normal and nobody remembers when it wasn't.
We treat the query layer as a first-class part of the architecture, not an afterthought bolted on after the schema is decided. That means reading EXPLAIN plans before shipping a feature, not after a support ticket. It means knowing which queries run on every page load and which run once a day, because those deserve very different levels of scrutiny. Complexity in a system is rarely one big problem. It's usually a thousand small, boring ones, and the database is where most of them live.