Performance
Otimização
Engenharia de Software
Observabilidade
Boas Práticas

Software performance: the essential steps to start optimizing

Optimizing performance has order. Skipping diagnosis is the most common and most expensive mistake.

When an application slows down, most teams' instinct is to start tinkering. Change a library, add a cache, upgrade a bigger machine. It's the wrong reaction, and it's expensive, because it attacks symptoms before understanding the disease.

Performance has a method. There is a right order of steps, and it starts long before you touch a line of code. This article is for those who already understand that they need to optimize and want to know where to start in a disciplined way, without wasting weeks in the wrong place.

I'm not going to treat this as a list of tricks. Tricks solve specific cases and get old quickly. Method resolves any case and sustains itself.

Step 0: Define what “fast” means

First of all, answer: what is acceptable? "The system is slow" is not an actionable problem. "The listing page needs to respond in less than a second for 95% of requests" is.

Without a target, you never know when to stop. Optimization without a goal is a bottomless hole, you can always make it faster, and it always costs more effort to gain less. Defining acceptable response time limits, ideally by percentile, transforms a diffuse sensation into an objective criterion.

This step seems bureaucratic, but it's what separates an optimization effort from an endless hunt. And it's a product and business conversation as much as an engineering one: what's "fast enough" depends on what the user is trying to do.

Step 1: measure before stirring

The most important rule of this entire discipline: you don't optimize what you don't measure. Without instrumentation, any change is a guess, and guesses land by luck.

Instrument the application with metrics, structured logs and, ideally, distributed tracing. The goal is to answer a simple question: where is time being spent? The answer almost always surprises. The bottleneck is rarely where intuition points out.

A recurring pattern: the team swears that the problem is the language or framework, instruments, and discovers that 80% of the time is in a single database query. Without measuring, this team would have rewritten the entire application and the problem would still be there.

The tool matters less than the habit. It could be a complete observability solution or a well-placed log. What cannot be missing is the data.

Step 2: Attack the biggest bottleneck first

With the data in hand, prioritization becomes obvious. There's a powerful rule of thumb: Most slowdowns tend to come from a minority of causes. Attack the biggest one first.

Resist the temptation to make ten micro-optimizations that add up to little. Find the item that alone accounts for the largest chunk of time and resolve it. The gain from eliminating the main bottleneck is usually greater than that from all other improvements combined.

After solving for the largest, measure again. The bottleneck moved. The second largest is now the new target. Performance is an iterative process of measuring, correcting and remediating, not a single effort.

Step 3: start with the database

In most business applications, banking is where the most time is wasted. That's why it deserves priority attention. Three checks solve a huge fraction of problems:

  • Missing indexes. Queries that scan the entire table because an index is missing on the filtered column. It is the most common error and the cheapest to fix.
  • The N+1 problem. When the code does a query for the list and then an additional query for each item in the list. One hundred items saw one hundred and one queries. It is solved by loading the related data at once.
  • Queries that bring too much data. Searching the entire table to use three columns is a waste of database, network and memory.

These three fixes alone transform the perception of speed for many systems. And none of them require changing technology.

Step 4: use cache wisely

Cache is the most seductive and the most dangerous optimization. It delivers immediate gains and introduces a whole class of new bugs: outdated data.

The golden rule: only curl what can be slightly old without causing damage. And always explicitly define how the cache will be invalidated. Cache without an invalidation strategy is not optimization, it is a time bomb.

For sensitive data, balances, order status, information that changes and whose accuracy matters, think twice. In systems that deal with money or citizen decisions, correctness of data wins over speed. Showing a wrong number faster doesn't help anyone.

It is also worth remembering that cache exists in several layers: in the user's browser, in an intermediate layer, on the server, in the bank. Each solves a different problem and has its own invalidation cost. The beginner's mistake is to stack caches without understanding which is responding to what, and then, when a piece of data goes wrong, no one knows which layer it got stuck in. Consciously mapping where the cache operates is part of using it well.

Step 5: only then think about infrastructure

Upgrading a bigger machine or adding more instances is often the first step teams take. It should be one of the last.

Scaling infrastructure without first fixing code and banking bottlenecks is throwing money at the problem. You pay more to do the same inefficient work, just in parallel. The cost grows, and the inefficiency is still there, now more expensive.

When code optimization has already been done and the real limit is capacity, then infrastructure comes in. And the right way is almost always to scale horizontally, add instances, which requires the application to be stateless. This is an architectural decision that is worth making early, because fixing it later is laborious.

The error that invalidates all steps

There is a cultural flaw that sabotages any script: optimizing by intuition and celebrating without measuring the result. The team changes something, feels it has become faster and moves on. Without measurement after the change, you don't know if it got better, worse or nothing happened.

Every optimization needs a measurable before and after. Otherwise you're just moving code around and twisting.

The honest reflection: Most performance problems don't require geniuses or expensive tools. It requires discipline. Measure, prioritize, fix the biggest bottleneck, remediate. Teams that follow this order resolve in days what teams that guess cannot resolve in months.

Performance done well is less about talent and more about process. Those who internalize these steps stop putting out fires and start preventing them.

If your team keeps resolving slowness in the dark, perhaps the problem is not technical, but methodological. There are other articles on the blog about quality, observability and scalability that complement this roadmap. If you want to exchange ideas about how to structure this in your organization, it's worth talking.

Also read