How to Refresh Spring Boot Configurations at Runtime with @RefreshScope
This article explains why traditional Java apps require restarts for config changes, introduces Spring Boot's @RefreshScope for zero‑downtime hot‑reloading, details its core principles, provides step‑by‑step implementation, troubleshooting tips, best practices, and advanced use cases for dynamic configuration in production environments.
Why Dynamic Configuration Refresh Is Needed
In traditional Java applications, changing a configuration file requires a service restart, which leads to service interruption, loss of in‑memory state, and complex deployment procedures.
Service interruption: the application is unavailable during restart.
State loss: temporary data held in memory is cleared.
Operational complexity: requires elaborate release workflows.
Spring Boot’s @RefreshScope solves these problems by enabling hot‑updates of configuration without restarting the service.
@RefreshScope Core Principle
1. Working Diagram
graph TD
A[Modify config file] --> B[Send POST refresh request]
B --> C[/actuator/refresh endpoint]
C --> D[RefreshScope refresh mechanism]
D --> E[Destroy old Bean and create new Bean]
E --> F[New config takes effect immediately]2. Key Technical Details
Scope proxy: creates a dynamic proxy for the Bean to intercept method calls.
Configuration binding: re‑binds values annotated with @Value when the configuration changes.
Bean lifecycle management: destroys and re‑initialises Beans marked with @RefreshScope.
Complete Implementation Steps
Step 1 – Add Required Dependencies
<!-- pom.xml -->
<dependencies>
<!-- Spring Boot core -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Actuator for refresh endpoint -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Spring Cloud Config support -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
<version>3.1.3</version>
</dependency>
</dependencies>Step 2 – Enable Refresh Mechanism
// Main application class
@SpringBootApplication
@EnableRefreshScope // enable dynamic refresh
public class DynamicConfigApp {
public static void main(String[] args) {
SpringApplication.run(DynamicConfigApp.class, args);
}
}Step 3 – Configure application.yml
# Basic application config
app:
feature:
enabled: true
timeout: 5000
retry-count: 3
welcome-msg: "Hello, Dynamic Config!"
# Expose refresh endpoint
management:
endpoints:
web:
exposure:
include: refresh,health,infoStep 4 – Create a Dynamically Refreshable Bean
@Service
@RefreshScope // Bean supports runtime refresh
public class FeatureService {
@Value("${app.feature.enabled}")
private boolean featureEnabled;
@Value("${app.feature.timeout}")
private int timeout;
@Value("${app.feature.retry-count}")
private int retryCount;
@Value("${app.feature.welcome-msg}")
private String welcomeMessage;
public String getFeatureConfig() {
return String.format("""
Feature Enabled: %s
Timeout: %d ms
Retry Count: %d
Message: %s
""", featureEnabled, timeout, retryCount, welcomeMessage);
}
}Step 5 – Add a Test Controller
@RestController
@RequestMapping("/config")
public class ConfigController {
private final FeatureService featureService;
public ConfigController(FeatureService featureService) {
this.featureService = featureService;
}
@GetMapping
public String getConfig() {
return featureService.getFeatureConfig();
}
}Step 6 – Trigger Configuration Refresh
After modifying application.yml, send a POST request to the refresh endpoint:
curl -X POST http://localhost:8080/actuator/refreshExample response (list of changed keys):
["app.feature.timeout", "app.feature.welcome-msg"]Deep Dive into @RefreshScope
1. Scope Proxy Mechanism (pseudo‑code)
public class RefreshScopeProxy implements ApplicationContextAware {
private Object targetBean;
@Override
public Object invoke(Method method) {
if (configChanged) {
// destroy old bean
context.destroyBean(targetBean);
// create new bean
targetBean = context.getBean(beanName);
}
return method.invoke(targetBean, args);
}
}2. Refresh Scope Control Techniques
Scenario 1 – Refresh specific Bean properties only
@Component
@RefreshScope
public class PaymentService {
@Value("${payment.timeout}")
private int timeout; // refreshed
private final String apiVersion = "v1.0"; // not refreshed
}Scenario 2 – Refresh an entire configuration class
@Configuration
@RefreshScope
public class AppConfig {
@Bean
@RefreshScope
public FeatureService featureService() {
return new FeatureService();
}
@Value("${app.theme}")
private String theme;
}Production Best Practices
1. Secure the Refresh Endpoint
management:
endpoint:
refresh:
enabled: true
endpoints:
web:
exposure:
include: refresh
base-path: /internal
path-mapping:
refresh: secure-refresh
spring:
security:
user:
name: admin
password: $2a$10$NVM0n8ElaRgg7zWO1CxUdei7vWoQP91oGycgVNCY8GQEx.TGx.AaC2. Automatic Refresh via Config Center (Nacos example)
# bootstrap.yml
spring:
cloud:
nacos:
config:
server-addr: localhost:8848
auto-refresh: trueCommon Issues and Troubleshooting
Refresh not taking effect – ensure the Bean is annotated with @RefreshScope.
Refresh endpoint returns no changes – verify that the endpoint response lists modified keys.
Multiple instances out of sync – use Spring Cloud Bus ( curl -X POST http://host:port/actuator/bus-refresh) to broadcast refresh events.
Potential memory leaks – clean up resources in a @PreDestroy method.
Extended Scenarios
Dynamic feature toggles, runtime log‑level adjustments, and database connection‑pool tuning can all be driven by refreshed configuration:
# Enable a new feature instantly
feature.new-checkout.enabled=true
# Adjust log level at runtime
logging.level.root=DEBUG
# Change Hikari pool size dynamically
spring.datasource.hikari.maximum-pool-size=20Conclusion
✅ Zero‑downtime configuration updates.
✅ Immediate effect of application parameters.
✅ More flexible operational experience.
✅ Maximised resource utilisation.
Best‑practice recommendations:
Avoid using dynamic refresh for sensitive data such as passwords.
Combine with a configuration centre (Nacos, Config Server) for centralized management.
Secure the refresh endpoint in production environments.
Mastering dynamic configuration refresh empowers your Spring Boot applications to stay agile and resilient in cloud‑native deployments.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architect
Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
