Optimizing Performance
1. Enabling HTTP/2 Support
Example: Enable HTTP/2 with TLS
server:
http2.enabled: true
ssl.enabled: true # HTTP/2 requires TLS in browsers
port: 8443
2. Configuring GZip Compression (server.compression)
Example: Enable GZip compression
server:
compression:
enabled: true
mime-types: application/json,application/xml,text/html,text/css,text/plain
min-response-size: 1024
3. Using Connection Pooling
| Pool | Tuning Property |
|---|---|
| HikariCP (default) | spring.datasource.hikari.maximum-pool-size |
| Hikari idle | ...minimum-idle |
| Hikari leak detection | ...leak-detection-threshold |
| Apache HttpClient | PoolingHttpClientConnectionManager |
| Reactor Netty | ConnectionProvider.builder("X").maxConnections(N) |
4. Optimizing JPA Queries (N+1 problem)
Warning: N+1 happens when iterating an entity collection triggers a SELECT
per associated entity. Use
JOIN FETCH, @EntityGraph, or batch fetching.Example: JOIN FETCH to avoid N+1
@Query("SELECT o FROM Order o JOIN FETCH o.items WHERE o.userId = :uid")
List<Order> findOrdersWithItems(@Param("uid") Long uid);
5. Using Lazy vs Eager Fetching Strategies
| Strategy | When |
|---|---|
| LAZY (default for collections, ToMany) | Most cases |
| EAGER (default for ToOne) | Always-needed associations only |
| JOIN FETCH per query | Override LAZY at call site |
6. Implementing Database Indexing
Example: Composite index on JPA entity
@Entity
@Table(name = "orders", indexes = {
@Index(name = "idx_orders_user_status", columnList = "user_id, status"),
@Index(name = "idx_orders_created", columnList = "created_at")
})
public class Order { /* … */ }
7. Using Query Result Caching
Example: Cache service method with Spring Cache
@Cacheable(value = "users", key = "#id")
public UserDto get(Long id) { return repo.findById(id).map(UserDto::from).orElseThrow(); }
// Hibernate L2: spring.jpa.properties.hibernate.cache.use_second_level_cache=true
8. Configuring JVM Memory Settings (-Xmx, -Xms)
| Flag | Use |
|---|---|
-Xms |
Initial heap (set = -Xmx for prod) |
-Xmx |
Max heap |
-XX:MaxMetaspaceSize |
Metaspace cap |
-XX:+UseG1GC |
G1 GC (default in JDK 17+) |
-XX:+UseZGC |
Low-pause for large heaps |
-XX:MaxRAMPercentage=75.0 |
Container-aware sizing |
9. Profiling Application Performance
| Tool | Use |
|---|---|
| JFR (Java Flight Recorder) | Built-in low-overhead profiling |
| async-profiler | Flame graphs (CPU, allocation) |
| VisualVM / JProfiler / YourKit | Sampling/instrumentation |
Spring Boot Actuator /heapdump, /threaddump |
Snapshots |
10. Using @EntityGraph for Fetch Optimization
Example: EntityGraph for eager fetch
@EntityGraph(attributePaths = {"items", "customer"})
@Query("SELECT o FROM Order o WHERE o.id = :id")
Optional<Order> findFullOrder(@Param("id") Long id);
11. Implementing API Response Pagination
Example: Paginated API response
@GetMapping("/orders")
public Page<OrderDto> list(@PageableDefault(size = 50, sort = "createdAt,desc") Pageable p) {
return repo.findAll(p).map(OrderDto::from);
}
12. Using Async and Non-Blocking Operations
| Approach | When |
|---|---|
@Async + virtual threads |
Fire-and-forget tasks |
| WebFlux / Reactor | End-to-end non-blocking |
| Virtual threads (JDK 21) | spring.threads.virtual.enabled=true |
13. Optimizing Spring Boot Startup Time
| Technique | Effect |
|---|---|
spring.main.lazy-initialization=true |
Lazy bean creation |
AOT compilation (spring-boot:process-aot) |
Pre-process configs |
| GraalVM Native Image | Sub-second startup |
| CDS (Class Data Sharing) | -XX:ArchiveClassesAtExit |
| Trim dependencies | Fewer auto-configs to evaluate |
Actuator /startup |
Identify slow beans |