50+ Proven Tips to Slash Bugs in Your Backend Development

This article compiles over fifty practical tips covering database design, code practices, and cache usage to help developers dramatically reduce bugs, improve reliability, and boost overall software quality in everyday backend projects.

macrozheng
macrozheng
macrozheng
50+ Proven Tips to Slash Bugs in Your Backend Development

Introduction

Today we discuss how to reduce bugs in daily development, summarizing more than 50 practical points across three major areas: database, code, and cache usage.

1. Database Section

Key areas prone to bugs: slow queries, field considerations, transaction failures, deadlocks, master‑slave delay, data compatibility, classic SQL pitfalls.

1.1 Slow Queries

1.1.1 Index Hit

Queries without indexes or that fail to hit indexes cause slow performance. Indexes may become ineffective when:

Query conditions contain OR String fields are not quoted

Using LIKE with wildcards

Composite index columns are not in the leading position

Applying MySQL functions on indexed columns

Performing arithmetic on indexed columns

Using !=, <>, or NOT IN on indexed fields

Testing for NULL or NOT NULL Mismatched character sets in joins

MySQL optimizer prefers full table scan

1.1.2 Large Data Sets – Sharding

When a single table exceeds ~20 million rows (B‑tree height grows), performance degrades; consider sharding with middleware such as mycat or sharding-jdbc.

1.1.3 Unreasonable SQL

Avoid excessive joins (e.g., six tables) and too many indexes (more than five per table) as they hurt insert/update performance.

1.2 Field Considerations

1.2.1 Length Overflow

`name` varchar(255) DEFAULT NOT NULL

Validate input length to prevent overflow errors.

1.2.2 Nullability

Prefer NOT NULL with sensible defaults (0 or -1 for integers, empty string for text) to avoid null‑pointer issues.

1.2.3 Missing Fields

Ensure schema changes in testing are propagated to production scripts.

1.2.4 Emoji Support

Use utf8mb4 for columns that need to store emojis.

1.2.5 Text/Blob Caution

Store file paths instead of full files; use prefix indexes for large TEXT columns.

1.3 Transaction Pitfalls

1.3.1 @Transactional on non‑public methods

Spring AOP proxies ignore non‑public methods, so transactions won’t apply.

1.3.2 Self‑invocation

public class TransactionTest{<br/>  public void A(){ B(); }<br/>  @Transactional<br/>  public void B(){ /* insert */ }<br/>}

Direct calls bypass the proxy, causing transaction loss.

1.3.3 Swallowed Exceptions

@Transactional<br/>public void method(){<br/>  try{ /* insert */ }catch(Exception e){ logger.error("exception caught", e); }<br/>}

Catching exceptions without rethrowing prevents rollback.

1.3.4 rollbackFor Misuse

Spring rolls back only unchecked exceptions by default; specify rollbackFor for checked ones.

1.3.5 Engine Support

MyISAM does not support transactions; use InnoDB.

1.3.6 Thread Context

Transactional code must run in the same thread as the Spring proxy.

1.4 Deadlocks

Deadlocks occur when multiple transactions hold locks the other needs, reducing resource utilization.

1.4.1 Lock Scenarios

Primary key + RC

Unique secondary index + RC

Non‑unique secondary index + RC

No index + RC

Primary key + RR

Unique secondary index + RR

Non‑unique secondary index + RR

No index + RR

Serializable

1.4.2 Analysis Steps

Simulate deadlock

Run SHOW ENGINE INNODB STATUS Identify offending SQL

Analyze lock types

Review lock compatibility matrix

1.5 Master‑Slave Delay

Read‑after‑write may miss recent data if the slave lags; use the master for strong consistency or accept eventual consistency for less critical reads.

1.6 Data Compatibility

When adding new columns, define default values for existing rows; handle nulls carefully to avoid NPEs.

1.7 Classic SQL Tips

1.7.1 Large Pagination

Three solutions: use incremental IDs, limit page numbers, or employ sub‑queries to fetch IDs first.

select id,name from employee where id>1000000 limit 10;
SELECT a.* FROM employee a, (select id from employee where ... limit 1000000,10) b where a.id=b.id;

1.7.2 Batch Operations

Prefer batch inserts/updates (e.g., 500 rows per batch) over single‑row loops.

remoteBatchQuery(param);
for(int i=0;i<100000;i++){ remoteSingleQuery(param); }

2. Code Layer

2.1 Coding Details

2.1.1 Six Typical Null‑Pointer Issues

Wrapper type nulls

Chained calls

Equals left‑hand null

ConcurrentHashMap does not allow null keys/values

Direct array/collection access

Direct field access

if(object!=null){ String name = object.getName(); }

2.1.2 Thread‑Pool Usage

Avoid Executors.newFixedThreadPool (unbounded queue may OOM)

Use custom pools with clear naming

Isolate pools per business domain

Handle pool exceptions properly

2.1.3 Linear‑Safety Collections

Use thread‑safe structures like ConcurrentHashMap instead of HashMap in high‑concurrency scenarios.

Non‑thread‑safe: HashMap, ArrayList, LinkedList, TreeMap

Thread‑safe: Vector, Hashtable, ConcurrentHashMap

2.1.4 Date/Amount Precision

Calendar calendar = Calendar.getInstance();<br/>calendar.set(2019, Calendar.DECEMBER, 31);<br/>Date testDate = calendar.getTime();<br/>SimpleDateFormat dtf = new SimpleDateFormat("YYYY-MM-dd");<br/>System.out.println(dtf.format(testDate));

Using YYYY yields 2020‑12‑31; prefer yyyy.

public class DoubleTest {<br/>  public static void main(String[] args){<br/>    System.out.println(0.1+0.2);<br/>    System.out.println(1.0-0.8);<br/>    System.out.println(4.015*100);<br/>    System.out.println(123.3/100);<br/>    double amount1 = 3.15;<br/>    double amount2 = 2.10;<br/>    if(amount1 - amount2 == 1.05){ System.out.println("OK"); }<br/>  }<br/>}

2.1.5 Large File Handling

Avoid Files.readAllBytes for big files; use BufferedReader line‑by‑line or NIO channels.

2.1.6 Resource Closing

try (FileInputStream inputStream = new FileInputStream(new File("jay.txt"))) {<br/>  // use resources<br/>} catch (FileNotFoundException e) { log.error(e); } catch (IOException e) { log.error(e); }

2.1.7 Exception Handling Pitfalls

Avoid e.printStackTrace() Log exceptions appropriately

Do not catch generic Exception for everything

Never use exception handling as business logic

2.1.8 Concurrency Consistency (Check‑then‑Update)

Replace separate check‑then‑update with atomic DB update/delete to avoid race conditions.

if(deleteAvailableTicketById(ticketId) == 1){ /* proceed */ } else { return "No ticket"; }

2.2 External Interface Design

2.2.1 Parameter Validation

Validate length, format, and range before persisting to prevent DB errors.

2.2.2 Backward Compatibility

// Old interface<br/>void oldService(A,B){ newService(A,B,null); }<br/><br/>// New interface<br/>void newService(A,B,C);

2.2.3 Rate Limiting

Use Guava RateLimiter or Alibaba Sentinel to protect services from traffic spikes.

2.2.4 Security (Signing & Auth)

Critical APIs (e.g., transfers) must enforce authentication, signing, and verification.

2.2.5 Idempotency

Design APIs to be idempotent—use unique keys, tokens, database constraints, or distributed locks (Redis, Zookeeper) to prevent duplicate processing.

2.3 Third‑Party Calls

2.3.1 Timeout Handling

On remote call timeout, avoid updating local state; instead, query the remote system later to confirm outcome.

2.3.2 Retry Mechanism

Implement retries for transient failures, respecting idempotency.

2.3.3 Degradation Strategy

If a non‑essential downstream service fails (e.g., email), degrade gracefully—complete the primary flow and handle the optional step asynchronously.

2.3.4 Asynchronous Processing

Offload notification calls (SMS, email) to async threads to improve response time.

2.3.5 Exception Handling for Remote Calls

Define clear fallback logic, decide between retry or failure, and ensure eventual consistency.

3. Cache Section

3.1 Database‑Cache Consistency

3.1.1 Cache Patterns

Cache‑Aside (read‑through/write‑through)

Read‑Through/Write‑Through

Write‑Behind (asynchronous)

Most systems use Cache‑Aside: read cache first, fall back to DB on miss, then populate cache.

3.1.2 Delete vs Update Cache

Deleting stale cache entries avoids dirty reads compared to directly updating cache after DB writes.

3.1.3 Order of Operations

In Cache‑Aside, always write to the DB first, then delete or update the cache to prevent stale reads.

3.1.4 Ensuring Final Consistency

Cache‑aside double delete with delay

Retry deletion

Asynchronous log‑driven cache eviction

3.2 Cache Penetration

Cache penetration occurs when requests for non‑existent keys repeatedly miss the cache and hit the DB, causing unnecessary load.

Mitigation:

Validate request parameters at API entry

Cache empty results with short TTL

Use Bloom filters to pre‑check existence

3.3 Cache Avalanche

Cache avalanche happens when many keys expire simultaneously, flooding the DB.

Mitigation: stagger TTLs (e.g., base + random offset) and ensure Redis high‑availability.

3.4 Cache Breakdown (Hot‑Key Miss)

When a hot key expires, a burst of concurrent requests may bypass the cache and overload the DB.

Solutions:

Mutex lock (e.g., Redis SETNX) to allow only one thread to rebuild the cache

Never‑expire hot data and refresh asynchronously

3.5 Hot Key Handling

Scale Redis clusters, hash‑shard hot keys, or add a local JVM cache to distribute load.

3.6 Memory & Eviction

3.6.1 Capacity Planning

Cache only frequently accessed data; monitor memory usage to avoid OOM.

3.6.2 Redis Eviction Policies

volatile‑lru / allkeys‑lru volatile‑lfu / allkeys‑lfu volatile‑random / allkeys‑random volatile‑ttl noeviction

3.6.3 Data Structure Choice

Leaderboard → zset User info → hash Message queue / article list → list Tags / social sets → set Counters / locks →

string

Conclusion

This article summarizes more than fifty coding and architectural best practices to help developers reduce bugs and improve system reliability.

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.

Database Optimizationcode qualityCache Strategybug reduction
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

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.