Spring Boot Essentials

Developer Tools & Hot Reload

18 min Lesson 9 of 13

Developer Tools & Hot Reload

Every second you spend waiting for a full JVM restart is a second stolen from actual development. Spring Boot's spring-boot-devtools module attacks that problem from several angles: automatic class reloading, live configuration refresh, a persistent HTTP session between restarts, and a sensible set of development-friendly defaults — all without touching your production build.

Adding DevTools to Your Project

DevTools ships as a standard starter. Add it to pom.xml:

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

Or in Gradle (build.gradle):

developmentOnly 'org.springframework.boot:spring-boot-devtools'
Why optional / developmentOnly? Spring Boot's repackage goal automatically excludes all optional and developmentOnly dependencies from the executable fat-JAR. DevTools will never end up on the production classpath — zero risk of accidentally enabling restart behaviour in a live environment.

Automatic Restart — How It Works

DevTools watches the files on your classpath. The moment it detects a change — a recompiled .class file, a modified .properties or template — it triggers an application restart. The key insight is that it uses two ClassLoaders:

  • Base ClassLoader — loads third-party JARs (Spring, Hibernate, libraries). These change rarely, so the base ClassLoader is not discarded between restarts. It is created once and kept alive.
  • Restart ClassLoader — loads your own application code (the classes in target/classes). This one is discarded and recreated on every restart.

Because two-thirds of the JVM startup cost (loading and initialising third-party bytecode) is eliminated, the effective restart time is typically 1–3 seconds instead of 10–20 seconds for a clean JVM boot.

Trigger restarts from your IDE, not from the filesystem. IntelliJ IDEA does not compile-on-save by default. Enable Build > Build Project Automatically and then activate Registry > compiler.automake.allow.when.app.running (older IDEs) or the Advanced Settings > Allow auto-make option (IDEA 2021+). VS Code with the Java extension compiles incrementally and triggers DevTools restarts automatically.

Configuring the Watch Paths

By default DevTools monitors everything on the classpath. You can tune this in application.properties:

# Directories to exclude from the restart trigger (static assets, templates) spring.devtools.restart.exclude=static/**,public/**,templates/** # Watch an additional path that is NOT on the classpath spring.devtools.restart.additional-paths=src/main/resources/extra # Disable restart entirely (if you only want LiveReload) spring.devtools.restart.enabled=false

Excluding static/** and templates/** is a common optimisation: changing a Thymeleaf template or a CSS file does not require a JVM-level restart — a plain browser refresh is enough. Keeping those paths out of the restart trigger makes the cycle faster still.

LiveReload Integration

DevTools embeds a LiveReload server on port 35729. Install the free LiveReload browser extension (Chrome/Firefox/Safari) and your browser will automatically refresh the current page after each restart. For template and static-asset changes that did not trigger a restart, DevTools still sends the reload signal.

# Disable the embedded LiveReload server spring.devtools.livereload.enabled=false
Port conflict? If something else already listens on 35729, set spring.devtools.livereload.port=<other-port> and update the LiveReload extension settings to match.

Remote DevTools

DevTools can also connect to a remote application — a staging server running the devtools JAR — and push restart triggers over HTTP. This is useful in Docker-based workflows where you edit locally but run in a container.

Enable remote support in the application you are deploying (not recommended for public internet, only internal / VPN-protected hosts):

# application.properties on the remote server spring.devtools.remote.secret=my-secret-token

Then run the RemoteSpringApplication launcher locally, pointing it at the remote URL. Every time you recompile locally, the changed classes are uploaded and the remote server restarts within seconds.

Never expose a DevTools remote endpoint on the public internet. The remote secret is transmitted over HTTP (or HTTPS if you configure it). An attacker who knows the secret can trigger arbitrary class uploads. Keep remote DevTools strictly within private networks or Docker networks.

Development-Time Property Overrides

DevTools automatically applies a set of sensible defaults when it detects a development environment. Notable overrides include:

  • Thymeleaf caching disabled (spring.thymeleaf.cache=false) — template changes are visible immediately.
  • FreeMarker, Groovy, Mustache, and web MVC caching also disabled.
  • Logging level for web group set to DEBUG so request mappings, handler execution, and view resolution appear in the console.
  • H2 console enabled if you have H2 on the classpath.

You can inspect the full list in DevToolsPropertyDefaultsPostProcessor in the Spring Boot source. These overrides are applied via a lowest-precedence PropertySource, so any value you explicitly set in application.properties takes priority.

Persisting Sessions Across Restarts

By default DevTools serialises the HTTP session to disk before a restart and deserialises it afterwards. This means you stay logged in through every restart cycle — no more re-authenticating after every save. You can opt out:

spring.devtools.restart.persist-sessions=false

Global DevTools Settings

If you work across multiple projects and want a single shared DevTools configuration, create a file at ~/.config/spring-boot/spring-boot-devtools.properties (Spring Boot 2.3+) or the legacy path ~/.spring-boot-devtools.properties. Settings here apply to all DevTools-enabled projects on the machine:

# ~/.config/spring-boot/spring-boot-devtools.properties spring.devtools.restart.trigger-file=.trigger

The trigger file pattern is especially useful in IDEs that continuously compile: instead of restarting on every individual class-file change, DevTools only restarts when a specific file (e.g. .trigger) is touched. This prevents partial restarts during multi-file compilations.

DevTools vs JRebel vs Spring Loaded

DevTools is free, zero-configuration, and sufficient for the vast majority of projects. JRebel is a commercial product that hot-swaps classes without restarting the Spring context — useful for very large applications where even a 2-second restart disrupts flow. Spring Loaded is an open-source predecessor that is now largely superseded by DevTools. For most teams, DevTools hits the sweet spot.

Summary

spring-boot-devtools compresses the inner development loop from a 15-second full restart to a 1–3 second context reload using a dual-ClassLoader strategy. Pair it with IDE auto-compilation and the LiveReload browser extension and you get a near-instantaneous feedback cycle. Mark the dependency optional (Maven) or developmentOnly (Gradle) and it will never reach your production fat-JAR. In the next and final lesson you will bring everything together by building your first complete Spring Boot application from scratch.