Spring Boot
CPU usage
application performance
startup issues
troubleshooting

Spring boot applications consume 100 CPU at startup

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

High CPU usage during Spring Boot startup is not always a bug. Some spikes are normal because the JVM is loading classes, Spring is wiring beans, and libraries are performing validation or metadata scanning. The real task is to separate expected warm-up from pathological startup behavior and then reduce unnecessary work.

First Decide Whether the Spike Is Normal

A brief jump to full CPU for a few seconds can be acceptable, especially on small containers with one or two vCPUs. A problem exists when startup stays pegged much longer than expected, causes deployment failures, or blocks readiness probes.

Typical startup CPU consumers include:

  • class loading and bytecode verification
  • component scanning across large package trees
  • bean creation and proxy generation
  • JIT compilation during warm-up
  • schema migration tools such as Flyway or Liquibase

Do not optimize blindly until you know which one dominates.

Measure Before Tuning

Start with a simple timing signal inside the app, then use JVM tools if the spike looks abnormal.

java
1import org.slf4j.Logger;
2import org.slf4j.LoggerFactory;
3import org.springframework.boot.context.event.ApplicationReadyEvent;
4import org.springframework.context.event.EventListener;
5import org.springframework.stereotype.Component;
6
7@Component
8public class StartupTimer {
9    private static final Logger log = LoggerFactory.getLogger(StartupTimer.class);
10    private final long startedAt = System.currentTimeMillis();
11
12    @EventListener(ApplicationReadyEvent.class)
13    public void onReady() {
14        long elapsedMs = System.currentTimeMillis() - startedAt;
15        log.info("Application ready in {} ms", elapsedMs);
16    }
17}

If startup time is unstable across deployments, compare logs, heap size, CPU limits, and enabled profiles before changing code.

Narrow Component Scanning

One frequent cause is scanning a package tree that is much larger than necessary. Keep your @SpringBootApplication class near the root of your app packages, not at a parent namespace that drags in unrelated classes.

java
1import org.springframework.boot.SpringApplication;
2import org.springframework.boot.autoconfigure.SpringBootApplication;
3
4@SpringBootApplication
5public class BillingApplication {
6    public static void main(String[] args) {
7        SpringApplication.run(BillingApplication.class, args);
8    }
9}

If you need explicit scanning, scope it tightly:

java
1import org.springframework.context.annotation.ComponentScan;
2
3@SpringBootApplication
4@ComponentScan(basePackages = {
5    "com.example.billing.api",
6    "com.example.billing.service"
7})
8public class BillingApplication {
9}

Overly broad scanning causes extra reflection, classpath reads, and bean analysis at startup.

Reduce Eager Initialization

Not every bean needs to be created before the app starts serving traffic. Lazy initialization can reduce initial CPU at the cost of deferring some work to first use.

In application.properties:

properties
spring.main.lazy-initialization=true

You can also target a specific bean:

java
1import org.springframework.context.annotation.Lazy;
2import org.springframework.stereotype.Service;
3
4@Service
5@Lazy
6public class ReportExporter {
7    public void export() {
8        // expensive setup deferred until first use
9    }
10}

This is useful for rarely used integrations, admin clients, or heavy SDK wrappers.

Check Auto-Configuration and Migrations

CPU spikes are often caused by work performed by libraries, not your own code. Common examples:

  • database schema migrations
  • JPA entity scanning
  • template engine preloading
  • cloud SDK initialization
  • logging framework reconfiguration

If a feature is not needed, disable it explicitly. For example, if this service does not use SQL initialization:

properties
spring.sql.init.mode=never
spring.jpa.open-in-view=false

Do not disable subsystems casually, but do review defaults instead of accepting all auto-configurations.

Profile the Startup Path

When logs are not enough, use a profiler or jcmd/Java Flight Recorder to find hot methods. If one package dominates CPU, that is usually a better lead than broad guesswork.

A common workflow is:

  • run app locally with production-like config
  • capture startup profile
  • identify hottest methods and repeated class loading paths
  • fix one cause at a time

This is more reliable than toggling random properties.

Watch Container CPU Limits

In Kubernetes or other container platforms, a Java app can look CPU-bound simply because it is starting under a very small CPU quota. A service that starts comfortably on a laptop may struggle when constrained to 250m.

If readiness matters more than minimal CPU, provision enough startup headroom and tighten limits after measuring. Infrastructure settings are part of the diagnosis, not a separate concern.

Avoid Expensive Work in @PostConstruct

Developers often hide heavy startup work inside bean lifecycle hooks.

java
1import jakarta.annotation.PostConstruct;
2import org.springframework.stereotype.Component;
3
4@Component
5public class CacheWarmup {
6    @PostConstruct
7    public void init() {
8        // Avoid large remote fetches or huge in-memory precomputations here
9    }
10}

If the work is optional, run it asynchronously after readiness or on first demand. If it is required, at least log its timing clearly.

Common Pitfalls

  • Treating every short CPU spike as a defect instead of checking duration and impact.
  • Scanning a package tree that is much larger than the application actually needs.
  • Running expensive migrations or remote calls during bean initialization without measuring them.
  • Enabling lazy initialization globally without understanding the latency tradeoff.
  • Ignoring CPU limits and readiness settings in container environments.

Summary

  • High startup CPU can be normal, but long or unstable spikes need investigation.
  • Measure startup time and profile hotspots before tuning anything.
  • Reduce broad component scanning and unnecessary eager bean creation.
  • Review auto-configurations, migrations, and lifecycle hooks for hidden startup work.
  • Infrastructure limits can amplify the problem, so diagnose the runtime environment too.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.