Performance
Qualidade de Software
Engenharia
Observabilidade
Arquitetura

Software performance: what real cases teach about quality

Performance is not an engineering luxury, it is the difference between a product that scales and one that silently bleeds money.

Every team has experienced the scene. The product works perfectly in the demo, passes the tests, pleases the customer. Three months later, with real traffic, the application starts to choke. The pages take time. Support is full of complaints. And no one knows exactly where the problem is.

Performance rarely breaks down all at once. It degrades little by little, hidden behind metrics that seemed comfortable when the system had a hundred users and become unsustainable with a hundred thousand. The danger isn't the obvious peak, it's silent erosion.

I want to use this article to look at performance for what it really is: a quality decision that has direct consequences on cash flow, reputation and the ability to grow. Not as a problem of "optimizing code", but as a symptom of engineering maturity.

Performance is quality, not embellishment

There is a lazy culture that separates "making it work" from "doing it quickly", as if the second were an optional step for later. This separation is false. A slow system is a faulty system, only the fault manifests itself as user abandonment, not an error screen.

The thesis I defend is simple: performance is a non-functional requirement that needs to be treated with the same rigor as a functional requirement. If your definition of "ready" does not include behavior under load, your definition of ready is incomplete.

I've seen this painfully in digital government products. A public services portal can be technically correct and still fail on the day the registration or declaration deadline opens. On that day, peak access is the rule, not the exception. And it is exactly on that day that the citizen's trust is gained or lost.

Case 1: the bottleneck was in the bank, not in the code

A team spent weeks rewriting the application layer convinced that the problem was the language. They changed libraries, refactored functions, fought with the framework. Latency dropped a little.

When they finally instrumented the queries, the truth emerged: a single query without an index was scanning the entire table with each request. The problem was never the application. It was the famous N+1 in disguise, multiplied by each item on a list that grew every month.

The lesson is not technical, it is cultural. Without observability, metrics, traces, structured logs, you don't optimize, you guess. And guesswork is expensive. The team spent weeks in the wrong place because they had no way of seeing where time was actually consumed.

The rule remains: measure before moving. Optimization without measurement is superstition.

Case 2: the cache that lied

Another product solved your load problems with aggressive caching. It worked beautifully, until the data started to become outdated. Users saw old balances, statuses that had already changed, information that did not correspond to reality.

Performance was gained at the expense of correctness. And correctness, in systems that deal with money or citizen decisions, is non-negotiable.

The learning here is about explicit trade-offs. Cache is one of the most powerful tools out there, but every cache is a gamble that the data might get slightly old. This bet needs to be a conscious, documented decision, with a clear invalidation strategy, not a patch applied under pressure.

The common mistake is to treat cache as magic. When the team doesn't understand exactly what is being cached, for how long and why, caching stops being an optimization and becomes a source of bugs that are difficult to reproduce.

Case 3: the system that scaled vertically until it could no longer work

There's a classic pattern of a growing company: traffic increases, the answer is to hire a bigger machine. It works once, twice, three times. Until the day when there is no bigger machine, or it costs absurdly expensive.

One case I followed had exactly this limit. The system was monolithic, with state stored in local memory, which prevented multiple instances from running in parallel. Scaling horizontally required rewriting the way the application saved sessions.

The correction was not heroic. It was externalizing the state, making the application truly stateless and putting a balancer in front. From then on, growing became a matter of adding instances, something that cloud infrastructure solves almost automatically.

The strategic vision: architecture sets the growth ceiling long before code. Decisions made early on, when the product is small, determine how expensive it will be to scale when it is large.

What do these cases have in common

None of these problems were, in origin, a language or framework problem. All were problems of diagnosis, trade-off and architecture. Mature teams are not the ones that write the fastest code, they are the ones that understand where time is spent and make deliberate decisions about where to invest effort.

Three principles run across the three cases:

  • Measure before optimizing. Without data, you fix the wrong place.
  • Trade-offs need to be explicit. Every optimization exchanges one thing for another. Know what you are exchanging.
  • Architecture is destiny. The cost of scaling is defined by structural decisions, not implementation details.

The trap of premature and late optimization

There is a well-known saying in engineering that premature optimization is the root of many evils. It's true, but it's become an excuse. Teams use the phrase to ignore performance until the problem explodes into production.

The correct point is in the middle. Don't optimize what no one uses. But set acceptable response time limits early and measure against them. You don't need to optimize everything, you need to know when something has crossed the line into unacceptable.

The honest critical reflection is this: most performance disasters don't come from a lack of technical knowledge. It comes from a lack of visibility and culture. Teams that don't measure, that don't talk about expected load, that don't review the heaviest queries, will repeat the same mistakes regardless of the stack they use.

Performance as a business advantage

For those who lead, it is worth reversing the logic. Performance is not an engineering cost, it is a business lever. A fast product converts more, retains more and costs less to operate. A system that scales without rewriting frees the team to build instead of put out fires.

In the public sector, the argument is even more direct: a digital service that can handle peak demand is a service that fulfills its function. One that falls on the most important day destroys the trust that took years to build.

Software quality, in the end, is the sum of many small decisions taken seriously. Performance is one of the most visible, and one of the things that most separates products that grow from products that merely survive.

If your organization is experiencing performance degradation without understanding the cause, the first step is almost never to change technology, it is to gain visibility. There are other articles on the blog about quality, architecture and scalability that delve deeper into this path. If this is a problem that keeps you up at night, it's worth talking about.

Also read