00:00

Spring Boot DevTools

Last updated:

While you build an application, you change code dozens of times an hour. Stopping the application, starting it again and refreshing the browser after every change adds up to a lot of waiting. Spring Boot DevTools removes most of that waiting: it restarts your application automatically when code changes, refreshes the browser for you, and switches on settings that make development easier.

This tutorial shows how to add DevTools, how its fast restart works, how to set up your IDE, how to control what triggers a restart, and how to make sure it never reaches production.

1. What Is Spring Boot DevTools?

Spring Boot DevTools is an optional module, spring-boot-devtools, that adds features for development only:

FeatureWhat it does for you
Automatic restartRestarts the application within seconds when compiled code changes
LiveReloadRefreshes the browser automatically when pages, CSS or JavaScript change
Development defaultsTurns off template and resource caching and shows more error details
Global settingsLets you keep personal DevTools settings in one file for all projects
Remote supportCan push changes to an application running on another machine

DevTools switches itself off when the application runs as a packaged production JAR, so it is safe to keep in your project.

2. Why You Need DevTools

Without DevToolsWith DevTools
Stop the app, start it again, wait for it to bootSave the file; the app restarts by itself in a second or two
Template changes need a restart because pages are cachedTemplate changes show on the next browser refresh
Refresh the browser by hand after every CSS changeLiveReload refreshes it for you
Hunt for hidden error detailsError responses include the message and details during development

Suppose a full start takes 10 seconds and you restart 60 times a day. That is 10 minutes of waiting, every day, just for restarts. DevTools restarts are typically much faster, and they happen without you having to do anything.

3. Adding DevTools to Your Project

For Maven, add the dependency as runtime and optional:

pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

For Gradle, use the special developmentOnly configuration:

build.gradle
dependencies {
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
}
SettingWhy it is there
runtime scopeYour code never refers to DevTools classes, so it is not needed for compiling
optional (Maven)Stops DevTools from passing on to other projects that depend on yours
developmentOnly (Gradle)Available when running locally, but never packaged into the final JAR

No configuration is needed. Run the application from your IDE or with ./mvnw spring-boot:run, and DevTools is active.

4. Automatic Restart

DevTools watches the classpath, the folders your IDE or build tool compiles into. When a file there changes, the application restarts automatically.

4.1 Why the restart is fast: two classloaders

A Java classloader is the part of the JVM that loads classes. DevTools splits your application across two of them:

ClassloaderLoadsOn restart
Base classloaderClasses that do not change: Spring, Hibernate, Jackson and all other library JARsKept as it is
Restart classloaderYour own classes and resources, the ones you are editingThrown away and created again

Because the large libraries stay loaded, only your own code is loaded again, which is why a DevTools restart is usually much quicker than a cold start.

4.2 What triggers a restart

  • Changed Java classes, once they are compiled.
  • Changed configuration files on the classpath, such as application.properties or application.yml.

By default, files in static/, public/, templates/, resources/, META-INF/resources/ and META-INF/maven/ do not trigger a restart. Those changes are picked up without one, because DevTools turns caching off.

4.3 See it work

Start this controller, then change the message and save:

HelloController.java
@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello from version 1"; // change to "version 2" and save
    }
}

The log shows the restart, using a thread named restartedMain:

Console
[  restartedMain] c.j.demo.DemoApplication : Started DemoApplication in 0.6 seconds

Call /hello again and you get the new message. If you see restartedMain in the log, DevTools restart is active.

5. Setting Up Your IDE

DevTools restarts only after your code is compiled. How that happens depends on your IDE:

IDEWhat to do
IntelliJ IDEAEnable Settings → Build, Execution, Deployment → Compiler → Build project automatically, and Settings → Advanced Settings → Allow auto-make to start even if developed application is currently running. Or press Build → Build Project (Ctrl+F9 / ⌘F9) after changes.
Eclipse / Spring ToolsWorks out of the box: saving a file compiles it automatically
VS CodeWorks out of the box with the Java extension, which compiles on save
Command lineRun ./mvnw spring-boot:run and recompile in another terminal with ./mvnw compile

If saving a file does not restart the application, the code is almost always not being compiled yet. Check the IDE setting first.

6. Restart vs Hot Reload

DevTools restarts the application. It does not swap code into the running JVM. These are different techniques:

TechniqueHow it worksKeeps state in memory?Tools
Automatic restartThrows away your classes and starts the application context againNoSpring Boot DevTools
Debugger hot swapReplaces method bodies in the running JVMYesAny IDE debugger, but only for changes inside existing methods
Advanced hot reloadReloads classes, including new methods and fields, without a restartYesJRebel (commercial), HotswapAgent with a special JDK

For most Spring Boot work, DevTools restart is the simplest and most reliable choice. Your application always starts from a clean state, exactly as it would in production.

7. Controlling What Triggers a Restart

Fine-tune restart behavior in application.properties:

application.properties
# Add exclusions to the defaults (static/, templates/ and so on remain excluded)
spring.devtools.restart.additional-exclude=reports/**,exports/**

# Watch an extra folder that is not on the classpath
spring.devtools.restart.additional-paths=../shared-config

# How often to look for changes, and how long to wait for more changes before restarting
spring.devtools.restart.poll-interval=1s
spring.devtools.restart.quiet-period=400ms
PropertyMeaning
spring.devtools.restart.enabledTurn automatic restart on or off (LiveReload and other features stay on)
spring.devtools.restart.excludeReplaces the default exclusion list
spring.devtools.restart.additional-excludeAdds to the default exclusion list; usually the one you want
spring.devtools.restart.additional-pathsExtra folders to watch for changes
spring.devtools.restart.poll-intervalTime between checks for changed files
spring.devtools.restart.quiet-periodWaits this long without further changes, so a burst of saves causes only one restart
spring.devtools.restart.trigger-fileRestart only when this specific file changes

7.1 Restart only when you say so

If your IDE compiles continuously, the application may restart more often than you like. A trigger file puts you in control: DevTools then restarts only when that one file changes:

application.properties
spring.devtools.restart.trigger-file=.reloadtrigger

Create an empty .reloadtrigger file on the classpath, for example in src/main/resources, and update it whenever you want a restart. Some IDEs can do this with one click.

7.2 Switching restart off completely

To disable restart regardless of any configuration file, set a system property before the application starts:

DemoApplication.java
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        System.setProperty("spring.devtools.restart.enabled", "false");
        SpringApplication.run(DemoApplication.class, args);
    }
}

8. LiveReload

DevTools starts a small LiveReload server on port 35729. When a browser is connected to it, the page refreshes automatically after a restart or after changes to HTML templates, CSS or JavaScript.

  1. Install a LiveReload extension in your browser.
  2. Start your application with DevTools.
  3. Open your page and switch the extension on for that tab.
  4. Change a template or stylesheet: the page refreshes by itself.

LiveReload is most useful for server-rendered pages, for example with Thymeleaf. If you build a separate front end with a tool like Vite or the Angular CLI, that tool usually has its own automatic refresh, and you can turn LiveReload off:

application.properties
spring.devtools.livereload.enabled=false

9. Development-Friendly Defaults

Some Spring Boot defaults are right for production but awkward during development. DevTools quietly changes a number of them while it is active:

Setting changed by DevToolsEffect during development
Template caching off (Thymeleaf, FreeMarker, Groovy templates, Mustache)Template edits appear on the next refresh, without a restart
Static resource caching offUpdated CSS, JavaScript and images are served immediately
Error details included (message, binding errors, stack trace)Error responses show what went wrong
H2 console enabledBrowse an in-memory H2 database at /h2-console
Persistent HTTP sessionsLogged-in sessions can survive a restart

These changes apply only while DevTools runs, so production keeps its safe, fast defaults. To switch them off and use your own settings, set spring.devtools.add-properties=false.

10. Global Settings for All Projects

Some DevTools settings are personal preferences, such as a trigger file or turning LiveReload off. Rather than adding them to every project, put them in one global file in your home folder:

~/.config/spring-boot/spring-boot-devtools.properties
spring.devtools.restart.trigger-file=.reloadtrigger
spring.devtools.livereload.enabled=false

These settings apply to every Spring Boot application you run on your machine that uses DevTools, and they never end up in a shared repository. A .yml or .yaml file in the same folder also works. Older versions used ~/.spring-boot-devtools.properties, which is still read when the newer folder does not exist.

11. Remote DevTools

DevTools can also update an application running on another machine, such as a development server, by sending your changed classes to it over HTTP. Both sides need setup:

pom.xml (remote application)
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <!-- keep DevTools inside the packaged JAR -->
        <excludeDevtools>false</excludeDevtools>
    </configuration>
</plugin>
application.properties (remote application)
spring.devtools.remote.secret=a-long-random-secret-value

On your own machine, run org.springframework.boot.devtools.RemoteSpringApplication from the IDE, with the remote URL as the program argument, for example https://dev.example.com. Changes you compile locally are then pushed to the remote application, which restarts.

Use this with great care. Anyone who knows the secret can change the code of the running application. Only enable it on trusted development servers, always over HTTPS, and never on production.

12. Keeping DevTools Out of Production

DevTools disables itself automatically in two ways:

  • It is not packaged. The Spring Boot Maven plugin leaves DevTools out of the final JAR by default, and Gradle’s developmentOnly configuration is never packaged.
  • It turns itself off when the application is started with java -jar as a fully packaged application, even if DevTools were somehow included.

You can confirm that it is gone from the JAR:

Terminal
./mvnw clean package
jar tf target/demo-0.0.1-SNAPSHOT.jar | grep devtools   # prints nothing: not packaged

Also check the production startup log: the main thread should be named main, not restartedMain.

13. Troubleshooting

ProblemLikely causeFix
Saving a file does nothingThe IDE is not compiling automaticallyEnable automatic build, or build manually (section 5)
Restarts happen constantlyA tool keeps writing files to the classpath, such as generated sources or logsExclude that folder with additional-exclude, or use a trigger file
Two restarts for one changeThe IDE saves several files a moment apartIncrease spring.devtools.restart.quiet-period
ClassCastException: X cannot be cast to XThe same class was loaded by both classloadersTell DevTools which JARs belong to the restart classloader (see FAQ)
Template changes do not appearA custom template setting re-enables cachingRemove cache=true settings from development properties
No restartedMain in the logDevTools is not on the classpath, or the app runs as a packaged JARCheck the dependency and run from the IDE or spring-boot:run

14. Best Practices

  • Add DevTools as optional/runtime in Maven or developmentOnly in Gradle, so it never reaches production.
  • Set up automatic compiling in your IDE, so restarts happen on save.
  • Use additional-exclude rather than exclude, to keep the sensible default exclusions.
  • Keep personal preferences in the global settings file, not in shared project files.
  • Use a trigger file if automatic restarts interrupt your flow.
  • Do not rely on in-memory state surviving restarts; use a database, even an embedded one, for test data.
  • Avoid Remote DevTools except on trusted development servers, and never in production.

15. Advantages and Limitations

AdvantagesLimitations
Much faster feedback after code changesRestart, not true hot reload: in-memory data is lost
No manual stop and startNeeds automatic compiling in some IDEs
Template and static changes show instantlyRare classloader issues with some libraries
Helpful error details and the H2 console during developmentLiveReload needs a browser extension
Safe by default: off in packaged production JARsRemote DevTools carries security risks

16. Summary

Spring Boot DevTools makes development faster with almost no setup. Add one dependency, set your IDE to compile automatically, and your application restarts within moments of every change, thanks to its two-classloader design. LiveReload refreshes the browser, development-friendly defaults turn off caching and show error details, and a global file keeps your personal preferences. DevTools stays out of production on its own; confirm it with a quick check of your packaged JAR.