Slow first call after restarting Spring Boot application

Quick update we followed @willermo's answer plus a couple of tips from another forum have led us in the right direction to fix the problem.

We logged the class loading using the -verbose:class flag, which made it clear that the problem were classes being lazy loaded at the moment of the first call.

To pre-load these classes, we used an ApplicationRunner to trigger the calls on application startup, as suggested by @willermo; this allowed us to deterministically warm up all the servers behind the load balancer with a single call for each.

There were a couple extra obstacles that were easy to fix:

  • Adding the ApplicationRunner broke all our tests, so we had to exclude it from the test profile.
  • We did not want to persist the effects on the DB of these "fake" calls, so we wrapped them in a transaction that we rollback in the end.

This was our final solution:

@Component
@Profile("!test")
public class AppStartupRunner implements ApplicationRunner {

  // [Constructor with injected dependencies]

  @Transactional
  @Override
  public void run(ApplicationArguments args) throws Exception {
    // [Make the calls]
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();    
  }
}


You can try to make the warm up call using an application runner.

public interface ApplicationRunner

Interface used to indicate that a bean should run when it is contained within a SpringApplication. Multiple ApplicationRunner beans can be defined within the same application context and can be ordered using the Ordered interface or @Order annotation.

e.g.

@Component
public class AppStartupRunner implements ApplicationRunner {


  @Override
  public void run(ApplicationArguments args) throws Exception {
    System.out.println("Running");
    //Make the first call here 
  }
}

Application Runner