Spring Boot DevTools
Spring Boot DevTools is a development-time dependency that shortens the edit-run-test feedback loop. It restarts your application automatically when classes change, refreshes the browser via LiveReload, and applies development-friendly defaults, all of which switch off automatically when you run a packaged application. It is the single fastest quality-of-life upgrade for local development.
Adding the dependency
DevTools is a normal Spring Boot starter-style dependency, marked optional so it never leaks into downstream artifacts.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
dependencies {
developmentOnly 'org.springframework.boot:spring-boot-devtools'
}
Note:
optional/developmentOnlymatters. It prevents DevTools from being transitively pulled into other modules that depend on yours, and it ensures the dependency is absent from the final fat JAR.
Automatic restart
When DevTools is on the classpath, Spring Boot watches your build output. Whenever a class file on the classpath changes, typically because your IDE recompiled a file, the application restarts.
This restart is much faster than a cold start because DevTools uses two class loaders:
- A base class loader holds unchanging third-party JARs (your dependencies).
- A restart class loader holds your application classes, the ones you actually edit.
On a change, only the restart class loader is discarded and recreated; the base class loader and its loaded JARs are reused. The result is a restart measured in fractions of a second rather than seconds.
INFO Restarting due to 1 class path change (1 addition)
INFO Started DemoApplication in 0.42 seconds (process running for 14.7)
Tip: A restart is triggered by a change to the compiled output, not the source file. In IntelliJ IDEA, either enable “Build project automatically” or press the build shortcut so recompilation happens, that is what kicks off the restart.
LiveReload
DevTools embeds a LiveReload server. With the LiveReload browser extension installed, your browser refreshes automatically whenever a resource (a template, CSS file, or static asset) changes, so you see UI edits without a manual reload. The server starts on port 35729 by default and can be disabled:
spring.devtools.livereload.enabled=false
Development-friendly property defaults
DevTools applies a set of sensible development defaults so you do not have to. The most common are template-engine caching switches, which are normally on for performance but get in the way while editing.
| Property | Production default | DevTools default |
|---|---|---|
spring.thymeleaf.cache | true | false |
spring.freemarker.cache | true | false |
spring.web.resources.cache.period | set | disabled |
spring.h2.console.enabled | false | (commonly enabled in dev) |
These defaults apply only while DevTools is active, so production behavior is unchanged. You can always override any of them in your own properties.
Customizing what triggers a restart
Some paths should not cause a restart, for example static resources that LiveReload already handles. Exclude them with spring.devtools.restart.exclude:
# Don't restart on changes to these paths
spring.devtools.restart.exclude=static/**,public/**,templates/**
# Disable restart entirely (keep LiveReload + property defaults)
spring.devtools.restart.enabled=false
You can also point DevTools at extra directories to watch with spring.devtools.restart.additional-paths.
DevTools is disabled in production automatically
This is the most important guarantee: DevTools deactivates itself when running from a packaged JAR. It detects that it was launched via java -jar (a “production” launch) and disables restart, LiveReload, and the property defaults. Combined with the optional/developmentOnly scope, DevTools simply is not present in a properly built production artifact.
Warning: Never rely on DevTools behavior in production, and never relax its scope to include it in the fat JAR. The restart class loader and LiveReload server are development tools and add overhead and a needless open port if shipped.
If you ever need to force-enable it in a non-IDE environment for debugging, set the system property explicitly, but treat that as a temporary measure:
java -jar app.jar -Dspring.devtools.restart.enabled=true
Global settings across projects
DevTools reads an optional global config file from your home directory, handy for settings you want in every project without editing each one. Place a .spring-boot-devtools.properties file in $HOME:
# ~/.spring-boot-devtools.properties
spring.devtools.restart.trigger-file=.reloadtrigger
spring.devtools.livereload.enabled=true
A trigger file is a useful pattern: with restart.trigger-file set, DevTools only restarts when that specific file changes, not on every recompile. You touch the file when you actually want a restart, which avoids restarts on every keystroke-driven build.
# Force a restart only when you choose to
touch .reloadtrigger
Remote DevTools
DevTools can also connect to an application running on a remote host, tunneling restarts and LiveReload over HTTP. It is gated behind a shared secret and is strictly a development aid.
spring.devtools.remote.secret=changeme
Warning: Remote DevTools opens a remote code-update channel. Only ever enable it against a development or staging instance you control, never a production or internet-facing server.
When to use it
Add DevTools to every project during development, it costs nothing in production and removes the friction of manual restarts. Pair it with the running & packaging workflow: use spring-boot:run with DevTools while coding, then build a clean fat JAR (without DevTools active) for deployment.