Aug 20, 2024 · 3 min read · Real Engineering Lessons
Improving API Response Times by 60%
A critical workflow got slower as the platform grew. My first thought was infrastructure, but most of the improvement came from understanding what the application and database were actually doing.
At Softcraft, I worked on a government case management platform that supported thousands of operations every day. As the platform grew, one of its most important workflows became noticeably slower. It was still working, but users were waiting longer for information they needed throughout the day. During peak periods, the delay became even more visible. My first thought was that maybe the system had outgrown its current resources. We also talked about caching and whether part of the stack needed to change. Any of those ideas could be valid, but we didn’t have enough evidence yet.
Looking at the Request
The application was built with Java, Spring Boot, and PostgreSQL. The stack wasn’t the interesting part of the problem. We followed the critical requests from the API through the application and into the database. The endpoint was doing much more work than its response suggested. Some database queries were reading more information than the screen needed. Related data was loaded through several additional calls and some filters prevented the database from using its indexes correctly. Each issue looked small alone, but together they made a common workflow expensive. That’s one thing that can be misleading about performance work. The slow part isn’t always where the user sees the delay. Users experienced a slow workflow, but much of the delay came from how the application requested and assembled data.
The Changes We Made
We didn’t replace the framework or redesign the entire system. We adjusted the heaviest queries, removed unnecessary data from the response, improved how related records were loaded, and added indexes that matched the way the application actually searched the data. We also measured the workflow again after each meaningful change instead of assuming every optimization helped. The result was a response-time improvement of more than 60% in the critical workloads we addressed. The platform also behaved more consistently during periods of heavier use. The result was more than 60% faster for the critical workloads we worked on, without making the system harder to operate.
Performance and Context
It’s easy to look at a slow system and immediately reach for a larger solution. Sometimes more infrastructure is exactly what the system needs. Sometimes caching is appropriate. Sometimes an architectural change is justified. But each of those decisions creates costs as well as benefits. More servers don’t fix inefficient access patterns. A cache can hide a slow query while introducing invalidation problems. A rewrite can spend months reproducing behavior without addressing the original bottleneck. In this case, the better first step was to make the existing behavior visible. We needed to know which requests were slow, which queries they produced, how much data they loaded, and what changed under real usage. Once we had that information, the problem became much less mysterious. Since then, I try to understand the current behavior before suggesting a bigger solution. When an API becomes slow, I try not to begin with “Which technology should we add?” I begin with simpler questions:
- Where is the time being spent?
- Did the behavior change as the volume of data grew?
- Are we retrieving information the user never sees?
- Does the database have the same understanding of the query that we do?
- Can we improve one bottleneck without adding a new moving part?
We did discuss infrastructure and caching during the investigation, so those options weren’t ignored. They just weren’t what this problem needed. Once the changes were in production and the same workflow was more than 60% faster, the solution felt almost smaller than the discussion that came before it, but that was fine. The users had a faster platform and we didn’t add another component for the team to maintain.