June 20, 2026Engineering

How I Made An API Three Times Faster Without A Rewrite

A slow API almost never needs a rewrite. It needs you to find the handful of places where the time actually goes. Here is the order I work in, and how it added up to a 3x speedup across more than a hundred endpoints.
API Performance
Database Optimization
Redis Caching
PostgreSQL
Backend Engineering
The most expensive misconception in software is that a slow app needs to be rebuilt. Rewrites are enormous, risky, and they usually reintroduce the same problems in new clothes. The truth is that most slow apps are slow in a few specific places, and the job is finding those places instead of guessing at them. I once took a production API to roughly three times its previous speed across more than a hundred endpoints, with no rewrite, just by going after the real bottlenecks in the right order. Here is that order. Before changing a single line, you have to know where the time actually goes. Developers are reliably wrong about this. The endpoint everyone assumes is slow is often fine, and the real culprit is something nobody suspected. So the first step is never a fix. It is profiling the app under conditions close to production and letting the data point at the problem. This matters for an unglamorous reason too. If you do not have a before number, you can never prove the after number meant anything. Every fix I make is bracketed by a measurement on the same workload, so the improvement is a fact, not a feeling. The most common cause of a slow endpoint, by a wide margin, is the N+1 query. You load a list of fifty things, and somewhere in the code each of those fifty things quietly triggers one more query to fetch something related. Now a page that should hit the database once or twice hits it fifty one times. The code looks clean. The database is on fire. These hide everywhere, especially behind convenient data access patterns that make the extra queries invisible in the source. Finding and collapsing them, loading the related data in one query instead of one per row, is frequently the single biggest win available, and it is usually the first thing I fix once the profiler shows me where they are. The next layer down is indexing. A query that filters or sorts on a column with no index forces the database to scan the entire table every time. On a small table you never notice. On a table that has grown for a year, it is the difference between a few milliseconds and a few seconds. The database usually tells you exactly which queries are scanning when it should be seeking, if you ask it. Adding the right indexes, and only the right ones, because every index has a write cost, often turns the heaviest queries from painful to instant without touching the application code at all. Some slowness is not a missing index, it is a query doing too much. Joins that pull far more than they need, aggregations computed on every request, subqueries that could be expressed better. These take real reading, but they reward it. Rewriting a single heavy query to ask the database a smarter question can collapse a slow endpoint on its own. Once the queries are honest, the last big lever is caching. A lot of endpoints recompute the same expensive answer over and over for data that barely changes. Putting a cache like Redis in front of those answers means the work happens once and the next thousand requests get the stored result in a fraction of the time. Caching is powerful and also the easiest place to create subtle bugs, so it comes last, after the underlying queries are already fast. Caching a slow query just hides the problem until the cache misses. Caching a fast query that genuinely repeats is close to free speed. Each of these is multiplicative, and doing them in this sequence is what added up to roughly three times faster across the whole API. The system I did this on serves more than 150 client organizations, so the speedup was not academic, it was felt by real users every day. None of it required a rewrite. It required measuring, fixing the biggest thing, measuring again, and stopping when the curve flattened. If your app works but drags, that is the work I do. The full breakdown is on the API and Database Performance service page. If your performance problem is really an infrastructure problem, falling over under load rather than just being slow, the Cloud and Kubernetes Migration service is the companion to this one. Does slow mean I need a rewrite? Almost never. Most apps are slow in a few specific places, and measuring instead of guessing usually finds a handful of bad queries carrying most of the pain. What is an N+1 query? Loading a list that quietly fires one extra query per item, so fifty rows means fifty one database hits. It is the most common cause of slow endpoints I see. How do you prove the speedup? You measure the same workload before and after. If the number does not move, the change does not ship. Can you do this on my API? Yes, it is one of my services. The service page explains how an engagement works.

Frequently asked questions

Does a slow app mean I need to rewrite it?

Almost never. Most slow apps are slow in a small number of specific places, not everywhere at once. When you measure instead of guess, you usually find a handful of bad queries and missing indexes carrying most of the pain, and fixing those gets you most of the speedup for a fraction of a rewrite's cost.

What is an N+1 query and why does it matter so much?

It is when loading a list of items quietly fires one extra query per item, so a page showing fifty rows hits the database fifty one times instead of once or twice. It is the single most common cause of slow endpoints I see, and it usually hides behind clean looking code.

How do you prove the speedup is real?

You measure the same workload before and after. If the number does not move, the change does not ship. A performance fix that is not backed by a before and after measurement is just a guess wearing a confident face.

Can you do this on my API?

Yes, this is one of my services. The API and Database Performance service page explains how an engagement works, and you can book a call from there.
How I Made An API 3x Faster Without A Rewrite | Kevin Gabeci