Backend Development 30 min read

36 Essential Tips for Designing Robust Backend APIs

This article presents 36 practical guidelines for backend engineers covering interface parameter validation, compatibility, extensibility, idempotency, logging, error handling, security, rate limiting, caching, transaction management, and more, helping you design reliable, maintainable, and high‑performance APIs across any language.

macrozheng
macrozheng
macrozheng
36 Essential Tips for Designing Robust Backend APIs

Preface

As backend developers, regardless of language (Java, Go, C++), the underlying backend thinking is similar. This series will share design and specification ideas to help daily work.

Our main job is to design good interfaces, so here are 36 tips for designing robust APIs, the first article of the series.

1. Interface Parameter Validation

Validate both input and output parameters. Check for null, length, format, etc., to avoid low‑level bugs such as inserting an over‑length string into a varchar(16) column.

For example, if a database column is varchar(16) and a 32‑character string is sent without validation, the insert will fail.

Similarly, avoid returning

null

for non‑nullable response fields.

2. Compatibility When Modifying Old Interfaces

Never change a public interface without maintaining backward compatibility; doing so can cause release failures.

For example, when adding a new parameter

C

to a Dubbo service, keep the old method and forward a

null

for the new argument:

<code>// old interface
void oldService(A, B) {
    // adapt to new interface
    newService(A, B, null);
}

// new interface (cannot delete old one yet)
void newService(A, B, C) {
    ...
}
</code>

3. Design for Extensibility

Consider business scenarios and design interfaces that can be extended without breaking existing callers. For example, a generic “face‑verification” API can serve employee onboarding, payment, or other modules by adding new enums rather than new endpoints.

4. Duplicate‑Request Handling

If the front end may resend a request, decide whether to filter duplicates. For read‑only queries it is unnecessary, but for updates—especially financial transactions—use Redis or a database unique key (e.g., transaction ID) to prevent repeats.

5. Thread‑Pool Isolation for Critical Interfaces

Important APIs such as login, transfer, or order should use dedicated thread pools; a bug in one service that exhausts a shared pool would affect the whole system.

6. Third‑Party Calls: Exception & Timeout

When invoking external services, handle exceptions, set reasonable timeouts, and decide on retry policies based on business impact.

Exception handling – decide whether to retry, fail fast, or alert.

Timeout – protect your thread pool from hanging calls.

Retry count – align with business tolerance.

7. Circuit Breaker & Degradation

In distributed systems, a failure in a downstream service can cause a cascade (service avalanche). Use circuit breakers or feature switches (e.g., Hystrix) to isolate failures.

If service C slows down due to a slow SQL, B and A will also be delayed, eventually exhausting resources and causing a system‑wide outage.

8. Logging

Key business code must have sufficient logs: entry parameters, exceptions, and outcomes. Example for a transfer service:

<code>public void transfer(TransferDTO transferDTO) {
    log.info("invoke transfer begin");
    log.info("invoke transfer, parameters:{}", transferDTO);
    try {
        res = transferService.transfer(transferDTO);
    } catch (Exception e) {
        log.error("transfer fail, account:{}", transferDTO.getAccount());
        log.error("transfer fail, exception:{}", e);
    }
    log.info("invoke transfer end");
}
</code>

See my “15 Logging Tips” article for more details.

9. Single‑Responsibility for Interfaces

An interface should do one thing. For example, a login API should only validate credentials and return a userId, not also handle registration or configuration queries.

10. Asynchronous Processing When Appropriate

Use async handling (thread pool or message queue) for non‑critical follow‑up actions such as sending emails after user registration.

11. Parallel Calls to Reduce Latency

When an endpoint needs data from multiple services (e.g., user info, banner, popup), invoke them in parallel using

CompletableFuture

to cut total response time.

12. Batch Processing

Avoid per‑item loops for database writes or remote calls; batch them instead. Example:

<code>// Bad
for (int i = 0; i < n; i++) {
    remoteSingleQuery(param);
}
// Good
remoteBatchQuery(param);
</code>

Kafka’s high throughput also relies on batch messaging.

13. Caching

Cache read‑heavy, write‑light data. Use Redis for distributed cache or Guava/Caffeine for local cache, and handle consistency, cache penetration, and cache avalanche scenarios.

14. Hot‑Data Isolation

Separate hot data by business, system, user, or data isolation (e.g., dedicated cache clusters) to prevent spikes from overwhelming the whole system.

Business isolation – e.g., split ticket‑selling periods.

System isolation – separate services on different hosts.

User isolation – allocate better machines for VIP users.

Data isolation – dedicated cache or DB for hot keys.

15. Configurable Parameters (e.g., Red‑Packet Skins)

Move variable UI elements into configuration tables so that changing a skin or pagination size does not require code changes.

<code>if (duringChristmas) {
    img = redPacketChristmasSkin;
} else if (duringSpringFestival) {
    img = redSpringFestivalSkin;
}
</code>

16. Idempotency

Ensure that repeated requests (e.g., double‑clicking a payment button) have the same effect as a single request. Distinguish idempotency from simple duplicate‑request filtering.

Idempotency means multiple identical requests produce the same result as one request.

Common implementations include primary‑key conflicts, token tables, distributed locks, etc.

17. Read‑Write Separation

Use a master for writes and slaves for reads, but be aware of replication lag.

18. Pagination for Large Result Sets

When an interface returns too much data, paginate or split the response.

19. SQL Optimization

Focus on explain plans, profiling, indexing, covering indexes, left‑most prefix, join optimization, large‑page handling, and sharding when data grows.

20. Lock Granularity

Lock only the necessary scope; avoid coarse‑grained locks that block unrelated operations.

<code>// Bad – lock whole object
synchronized (this) { ... }
// Good – lock only shared list
synchronized (data) { ... }
</code>

21. Unified Error Codes

Define clear status codes and messages for success, failure, processing, etc., and avoid exposing raw exceptions to clients.

22. Exception Handling Best Practices

Prefer logging over

e.printStackTrace()

.

Log full exception details when catching.

Avoid catching generic

Exception

unless necessary.

Use

finally

or try‑with‑resources to close streams.

Match caught exceptions with thrown ones.

Never swallow caught exceptions.

Encapsulate custom exceptions preserving the cause.

Pre‑check for runtime exceptions (e.g., NPE) instead of catching them.

Catch specific exceptions before generic ones.

23. Optimize Business Logic

Write clear, well‑commented code; avoid unnecessary database calls; pass objects instead of re‑querying IDs.

24. Large Files, Transactions, Objects

Read large files with streams (e.g.,

BufferedReader

) instead of loading whole bytes.

Avoid huge transactions that cause deadlocks or long rollbacks.

Beware of large objects that trigger full GC.

25. Rate Limiting

Protect the system under traffic spikes using Guava

RateLimiter

, Redis, or Sentinel for distributed limiting.

26. Runtime Exceptions Prevention

Check collection size before accessing indices to avoid

IndexOutOfBoundsException

and null checks to prevent NPEs.

<code>if (CollectionsUtil.isNotEmpty(list) && list.size() > 1) {
    String name = list.get(1).getName();
}
</code>

27. API Security

Use token authentication (store token in Redis with TTL) and request signing (client signs with private key, server verifies with public key). Encrypt payloads via HTTPS or custom symmetric encryption.

28. Distributed Transactions

Solutions include 2PC/3PC, TCC, local message tables, max‑effort notification, and Seata.

29. Common Transaction Pitfalls

Method must be public; private/final methods won’t be proxied.

Internal method calls bypass Spring proxies.

Methods not managed by Spring won’t start a transaction.

Multithreaded calls use different DB connections.

Unsupported storage engines.

Swallowing exceptions in try‑catch blocks.

Incorrect propagation settings.

30. Common Design Patterns

Apply patterns such as Strategy, Factory, Template Method, Observer, etc., to improve code reuse and maintainability.

31. Linear Safety (Thread‑Safety)

Use thread‑safe collections like

ConcurrentHashMap

instead of non‑thread‑safe ones (e.g.,

HashMap

) in high‑concurrency scenarios.

HashMap, ArrayList, LinkedList, TreeMap – not thread‑safe. Vector, Hashtable, ConcurrentHashMap – thread‑safe.

32. Clear Naming and Documentation

Write interfaces that are easy to understand and follow naming conventions to aid future maintenance.

33. API Versioning

Include a

version

field in request payloads to support backward compatibility when new features are added.

34. Code Quality

Eliminate duplicate code.

Encapsulate many parameters into DTOs.

Keep methods short.

Refactor complex if‑else chains.

Remove dead code.

Maintain consistent formatting.

Avoid over‑design.

35. Ensure Correctness

Self‑test APIs, guarantee data correctness under concurrency (e.g., CAS for balance deduction), and prevent overselling with distributed locks.

36. Communication

Collaborate with front‑end, product, and technical leads when defining interfaces; keep stakeholders aligned throughout development.

backendPerformancescalabilityValidationloggingsecurityAPI designIdempotency
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login 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.