10 Proven Techniques to Supercharge API Performance in Java Backends

This article presents a comprehensive, step‑by‑step guide to optimizing API latency in Java backend services, covering batch processing, asynchronous execution, caching, preprocessing, pooling, parallelization, indexing, transaction management, pagination, SQL tuning, and lock granularity, complete with code examples and diagrams.

Top Architect
Top Architect
Top Architect
10 Proven Techniques to Supercharge API Performance in Java Backends

Background

Legacy projects often suffer from excessive API response times, prompting a focused effort to improve interface performance.

Interface Optimization Summary

1. Batch Processing

Group database operations to reduce I/O by inserting or updating records in bulk after processing.

// for‑loop single insert
list.stream().forEach(msg -> {
    insert();
});
// batch insert
batchInsert();

2. Asynchronous Processing

Offload long‑running, non‑essential logic to asynchronous execution using thread pools, message queues, or scheduling frameworks.

Example: a financial purchase API can handle accounting and file writing asynchronously because the results are not required in real time.

3. Space‑for‑Time (Caching)

Cache frequently accessed, rarely changed data to avoid repeated database queries or calculations.

Example: cache stock‑tool rotation data that updates weekly, reducing costly DB lookups.

4. Preprocessing

Pre‑compute data and store it in a cache or a dedicated column so that API calls can retrieve ready‑made results, e.g., pre‑calculate annualized returns for financial products.

5. Pooling Concept

Reuse expensive resources such as database connections or threads via pools to avoid repeated creation overhead.

6. Serial to Parallel

Convert sequential dependent calls into parallel independent calls when there is no result dependency, dramatically reducing total latency.

Example: a portfolio display API can fetch account info, product info, and banner data in parallel.

7. Indexing

Proper indexing can greatly accelerate query performance; the article notes common scenarios where indexes may not be effective.

8. Avoid Large Transactions

Long‑running transactions hold database connections, causing contention. Example code shows a typical @Transactional method with multiple inserts.

@Transactional(value = "taskTransactionManager", propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = {RuntimeException.class, Exception.class})
public BasicResult purchaseRequest(PurchaseRecord record) {
    BasicResult result = new BasicResult();
    // insert account task
    taskMapper.insert(ManagerParamUtil.buildTask(record, TaskEnum.Task_type.pension_account.type(), TaskEnum.Account_bizType.purchase_request.type()));
    // insert sync task
    taskMapper.insert(ManagerParamUtil.buildTask(record, TaskEnum.Task_type.pension_sync.type(), TaskEnum.Sync_bizType.purchase.type()));
    // insert file upload task
    taskMapper.insert(ManagerParamUtil.buildTask(record, TaskEnum.Task_type.pension_sync.type(), TaskEnum.Sync_bizType.cert.type()));
    result.setInfo(ResultInfoEnum.SUCCESS);
    return result;
}

To prevent large‑transaction issues, avoid placing RPC calls inside the transaction, keep queries outside, and limit the amount of data processed within a single transaction.

9. Optimize Program Structure

Refactor accumulated code after multiple iterations to eliminate redundant queries and object creations, improving overall execution flow.

10. Deep Pagination Problem

Using LIMIT offset, count scans unnecessary rows. Replace with index‑based pagination:

SELECT * FROM purchase_record
WHERE productCode = 'PA9044' AND status = 4 AND id > 100000
LIMIT 200;

11. SQL Optimization

General SQL tuning (index usage, pagination, etc.) should be applied based on the specific query patterns.

12. Lock Granularity

Overly coarse locks degrade performance. Only lock shared resources; avoid locking non‑shared code.

// Incorrect: lock non‑shared and shared together
synchronized(this) {
    share();
    notShare();
}
// Correct: lock only shared part
synchronized(this) {
    share();
}

Conclusion

Interface performance issues usually accumulate over iterative development. By adopting batch processing, async execution, caching, preprocessing, pooling, parallelization, proper indexing, transaction hygiene, pagination strategies, SQL tuning, and fine‑grained locking, developers can significantly reduce latency and improve system efficiency.

PerformanceOptimizationAPI
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

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.