Refresh Spring Boot Config at Runtime Without Restart
This guide explains how to use Spring Boot's @RefreshScope to dynamically refresh configuration at runtime without restarting services, covering the underlying mechanism, step‑by‑step implementation, production best practices, troubleshooting tips, and advanced use cases.
Why dynamic configuration refresh is needed?
In traditional Java apps, changing a config file requires restarting the service, causing downtime, loss of in‑memory state, and complex deployment processes.
Service interruption: the service is unavailable during restart.
State loss: temporary data in memory is cleared.
Operational complexity: requires elaborate release procedures.
Spring Boot's @RefreshScope solves these problems by enabling hot configuration updates, allowing applications to reassemble like Lego blocks.
@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 techniques
Scope proxy: creates a dynamic proxy for beans to intercept method calls.
Configuration binding: re‑binds values annotated with @Value when configuration changes.
Bean lifecycle management: destroys and re‑initializes beans marked with @RefreshScope.
Complete implementation steps
Step 1: Add required dependencies
<!-- pom.xml -->
<dependencies>
<!-- Spring Boot starter -->
<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 starter for config refresh -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
<version>3.1.3</version>
</dependency>
</dependencies>Step 2: Enable refresh mechanism
@SpringBootApplication
@EnableRefreshScope // enable config refresh
public class DynamicConfigApp {
public static void main(String[] args) {
SpringApplication.run(DynamicConfigApp.class, args);
}
}Step 3: Configure application.yml
# Application basic 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 dynamic configuration bean
@Service
@RefreshScope
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: Create 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 /actuator/refresh:
curl -X POST http://localhost:8080/actuator/refreshThe response lists the changed properties, e.g., ["app.feature.timeout","app.feature.welcome-msg"].
Deep dive into @RefreshScope
1. Scope proxy principle (pseudo‑code)
public class RefreshScopeProxy implements ApplicationContextAware {
private Object targetBean;
@Override
public Object invoke(Method method) {
if (configChanged) {
context.destroyBean(targetBean);
targetBean = context.getBean(beanName);
}
return method.invoke(targetBean, args);
}
}2. Refresh scope control tricks
Only properties annotated with @Value are refreshed; other fields remain unchanged.
@Component
@RefreshScope
public class PaymentService {
@Value("${payment.timeout}")
private int timeout; // refreshed
private final String apiVersion = "v1.0"; // not refreshed
}Whole configuration classes can also be refreshed:
@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: <encrypted>2. Automatic refresh solutions
Git webhook or configuration center (e.g., Nacos) can trigger automatic refresh.
# bootstrap.yml
spring:
cloud:
nacos:
config:
server-addr: localhost:8848
auto-refresh: trueCommon troubleshooting
Problem 1: Refresh does not take effect
Ensure the bean is annotated with @RefreshScope.
Verify the refresh endpoint returns the modified properties.
Check logs with logging.level.org.springframework.cloud=DEBUG.
Problem 2: Multi‑instance refresh out of sync
Use Spring Cloud Bus to broadcast refresh events:
curl -X POST http://host:port/actuator/bus-refreshProblem 3: Configuration update causes memory leak
Clean up resources in a @PreDestroy method.
@PreDestroy
public void cleanUp() {
// release resources
}Extended scenarios
Dynamic feature toggles, runtime log level adjustment, and database connection pool tuning can all be handled with @RefreshScope:
# Enable new checkout feature at runtime
feature.new-checkout.enabled=true
# Adjust log level dynamically
@RefreshScope
public class LogConfig {
@Value("${logging.level.root}")
private String logLevel;
}
# Change Hikari pool size
spring.datasource.hikari.maximum-pool-size=20Conclusion
By leveraging @RefreshScope, you achieve zero‑downtime configuration updates, immediate effect of application parameters, more flexible operations, and optimal resource utilization. Follow best‑practice recommendations such as protecting the refresh endpoint and avoiding dynamic refresh for sensitive credentials.
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.
Java Tech Enthusiast
Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!
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.
