How to Diagnose and Fix Common API Performance Bottlenecks in Java Backend

This article walks through real‑world API performance complaints, identifies root causes such as slow MySQL queries, thread‑pool misconfiguration, lock contention and machine issues, and presents practical solutions ranging from pagination rewrites and index tuning to multithreading, caching and async callbacks.

Java Backend Technology
Java Backend Technology
Java Backend Technology
How to Diagnose and Fix Common API Performance Bottlenecks in Java Backend

Background

The system was completed in early 2021 and entered the promotion phase. As usage grew, many users praised the product but also complained about performance. Monitoring over a week revealed dozens of slow endpoints, several exceeding 5 seconds and one over 10 seconds, with overall stability below 99.8 %.

Performance complaint illustration
Performance complaint illustration

Which problems cause API performance issues?

Database slow queries

Deep pagination

Missing indexes

Index loss

Too many joins

Too many sub‑queries

Excessive IN list size

Large data volume

Complex business logic

Loop calls

Sequential calls

Thread‑pool design flaws

Lock design flaws

Machine problems (full GC, restarts, thread saturation)

Problem solutions

All slow‑query examples assume MySQL.

Deep pagination (MySQL)

Typical pagination: select name, code from student limit 100, 20 When the offset becomes large, MySQL scans many rows. A better approach is to use a primary‑key condition:

select name, code from student where id > 1000000 limit 20

This forces index usage but requires the caller to pass the last max ID.

Missing indexes

Check a table’s indexes with: show create table xxxx; Add appropriate indexes, but avoid low‑cardinality columns and schedule ALTER statements during low‑traffic windows.

Index loss

When MySQL ignores an index, investigate reasons such as type conversion, functions on indexed columns, or low selectivity. Force an index if necessary:

select name, code from student force index(XXXXXX) where name = '天才';

Too many joins or sub‑queries

Prefer reducing joins, splitting queries in code, and assembling results in memory when data sets are small. Excessive joins may cause temporary tables on disk, degrading performance.

Excessive IN list

If an IN clause contains thousands of values, split the query into batches or limit the size (e.g., 200 items):

if (ids.size() > 200) { throw new Exception("Batch size cannot exceed 200"); }

Large data volume

When a single table grows to billions of rows, consider sharding, partitioning, or migrating to a database designed for big data.

Complex business logic

Loop calls

Initialize a list of 12 months sequentially:

List<Model> list = new ArrayList<>();
for (int i = 0; i < 12; i++) {
    Model model = calOneMonthData(i);
    list.add(model);
}

Replace with a thread‑pool to compute months in parallel:

public static ExecutorService commonThreadPool = new ThreadPoolExecutor(
    5, 5, 300L, TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(10), commonThreadFactory,
    new ThreadPoolExecutor.DiscardPolicy());

List<Future<Model>> futures = new ArrayList<>();
for (int i = 0; i < 12; i++) {
    futures.add(commonThreadPool.submit(() -> calOneMonthData(i)));
}
List<Model> list = new ArrayList<>();
for (Future<Model> f : futures) {
    list.add(f.get());
}

Sequential calls

When tasks are independent, use CompletableFuture to run them concurrently:

CompletableFuture<A> futureA = CompletableFuture.supplyAsync(() -> doA());
CompletableFuture<B> futureB = CompletableFuture.supplyAsync(() -> doB());
CompletableFuture.allOf(futureA, futureB).join();
C c = doC(futureA.join(), futureB.join());
CompletableFuture<D> futureD = CompletableFuture.supplyAsync(() -> doD(c));
CompletableFuture<E> futureE = CompletableFuture.supplyAsync(() -> doE(c));
CompletableFuture.allOf(futureD, futureE).join();
return doResult(futureD.join(), futureE.join());

Thread‑pool design issues

Core threads, max threads and queue size must be tuned. An undersized core pool prevents parallelism; a saturated queue or max pool leads to task rejection.

Thread pool core threads
Thread pool core threads

Lock design issues

A coarse‑grained synchronized block can be split:

public void doSome() {
    File f = null;
    synchronized (this) {
        f = calData();
    }
    uploadToS3(f);
    sendSuccessMessage();
}

Machine problems

Full GC, thread leaks, or resource exhaustion can cause latency spikes; monitor and isolate such issues.

General “silver‑bullet” solutions

Caching

Cache frequently read, rarely changed data using in‑memory maps, Guava, or external stores like Redis, Tair or Memcached.

Simple Map cache

Guava local cache

Redis / Tair / Memcached distributed cache

Callback / async verification

For slow downstream calls (e.g., payment gateway), return a fast “processing” response and notify the caller later via callback or Kafka.

Fast success flow
Fast success flow

Conclusion

The article summarizes practical performance‑optimization techniques encountered in real projects, inviting further discussion and sharing.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backendperformanceoptimizationcachingthread pool
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.