Backend Development 8 min read

Five‑Step Optimization of a Category‑Tree Query in a SpringBoot Application

This article details a step‑by‑step performance improvement journey for a category‑tree query in a SpringBoot‑Thymeleaf system, covering Redis caching, scheduled jobs, local Caffeine cache, Gzip compression, and data slimming with byte‑array storage to resolve latency and large‑key issues.

IT Services Circle
IT Services Circle
IT Services Circle
Five‑Step Optimization of a Category‑Tree Query in a SpringBoot Application

The article begins with a brief introduction describing a simple category‑tree query feature commonly used in e‑commerce systems and the need to optimize it five times.

Background: The website uses SpringBoot with the Thymeleaf template engine for dynamic rendering. Initially, the API directly queried the database for category data, assembled a tree structure, and returned it to the front end.

First optimization: A Redis cache was introduced. The flow became: check Redis for the tree, return if present; otherwise query the database, build the tree, store it in Redis with a 5‑minute TTL, and return the result.

Second optimization: To avoid frequent cache misses, a scheduled Job was added to asynchronously refresh the category tree in Redis every five minutes, while retaining the original on‑demand fallback logic. The Redis TTL was changed to permanent.

Third optimization: A local in‑memory cache using Spring’s Caffeine was added. The request flow now checks the local cache first, falls back to Redis, and finally to the database if needed, updating both caches accordingly. The local cache also uses a 5‑minute expiration.

Fourth optimization: Because the tree grew to over ten thousand nodes, the response size (≈1 MB) caused slow page loads. Enabling Nginx Gzip compression reduced the payload to about 100 KB, improving transfer speed.

Fifth optimization: Redis stored the entire tree as a large JSON string, creating a big‑key problem. The solution involved slimming the data model by removing unnecessary fields and renaming JSON properties to short keys, then compressing the JSON with GZip into a byte array before storing it in Redis. Upon retrieval, the byte array is decompressed back to JSON and converted to the tree structure.

Code example of the original Category class:

@AllArgsConstructor
@Data
public class Category {
    private Long id;
    private String name;
    private Long parentId;
    private Date inDate;
    private Long inUserId;
    private String inUserName;
    private List<Category> children;
}

After slimming and renaming fields:

@AllArgsConstructor
@Data
public class Category {
    /** 分类编号 */
    @JsonProperty("i")
    private Long id;

    /** 分类层级 */
    @JsonProperty("l")
    private Integer level;

    /** 分类名称 */
    @JsonProperty("n")
    private String name;

    /** 父分类编号 */
    @JsonProperty("p")
    private Long parentId;

    /** 子分类列表 */
    @JsonProperty("c")
    private List<Category> children;
}

These successive optimizations eliminated performance bottlenecks, reduced Redis key size by tenfold, and ensured the category‑tree feature remained stable and fast for users.

Performance OptimizationRedisCachingcaffeineSpringBootThymeleafgzip
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

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.