Skip to main content

Overview

Spring Cloud Config allows you to update configuration at runtime without restarting services. This is critical for making quick changes to feature flags, connection strings, or operational parameters.
Configuration refresh is supported when services have the spring-boot-starter-actuator and @RefreshScope annotations on beans that consume configuration properties.

Refresh Strategies

There are two main approaches to refreshing configuration:

Individual Service Refresh

Call /actuator/refresh on each service that needs updated configuration.

Broadcast Refresh (Spring Cloud Bus)

Trigger a single refresh that propagates to all services via message bus.

Individual Service Refresh

Using the /actuator/refresh Endpoint

The refresh endpoint must be explicitly exposed in your configuration:
management:
  endpoints:
    web:
      exposure:
        include: health, info, refresh
By default, the refresh endpoint is not exposed in production configurations for security. Add it explicitly only when needed.

Refresh Workflow

1

Update Configuration in Git

Make changes to the YAML files in the sgivu-config-repo and commit them:
cd ~/workspace/source
# Edit configuration file
vim sgivu-auth-dev.yml

# Commit changes
git add sgivu-auth-dev.yml
git commit -m "Update auth service timeout configuration"
git push
2

Refresh Config Server (if needed)

The Config Server automatically detects Git changes, but you can force a refresh:
docker restart sgivu-config
Or if using /actuator/refresh on the Config Server itself:
curl -X POST http://localhost:8888/actuator/refresh
3

Refresh the Microservice

Trigger a refresh on the service that needs the updated configuration:
curl -X POST http://localhost:9000/actuator/refresh
The response shows which configuration keys were updated:
[
  "management.endpoints.web.exposure.include",
  "service.internal.timeout"
]
4

Verify the Changes

Confirm the new configuration is active by checking service behavior or logs.

Refreshing Multiple Services

If you updated shared configuration that affects multiple services, refresh each one:
# Refresh auth service
curl -X POST http://localhost:9000/actuator/refresh

# Refresh gateway
curl -X POST http://localhost:8080/actuator/refresh

# Refresh user service
curl -X POST http://localhost:8081/actuator/refresh

# Refresh client service
curl -X POST http://localhost:8082/actuator/refresh

# Refresh vehicle service
curl -X POST http://localhost:8083/actuator/refresh

Spring Cloud Bus for Broadcast Refresh

Overview

Spring Cloud Bus uses a message broker (RabbitMQ or Kafka) to broadcast refresh events to all services simultaneously.
┌─────────────┐
│   Config    │
│   Server    │  POST /actuator/bus-refresh
└──────┬──────┘


  ┌────────────┐
  │  RabbitMQ  │
  │     or     │
  │   Kafka    │
  └─────┬──────┘

   ┌────┴─────┬────────┬────────┐
   ▼          ▼        ▼        ▼
┌──────┐  ┌──────┐ ┌──────┐ ┌──────┐
│ Auth │  │  GW  │ │ User │ │Vehicle│
└──────┘  └──────┘ └──────┘ └──────┘

Setting Up Spring Cloud Bus

1

Add Dependencies

Add Spring Cloud Bus to each microservice:
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
2

Configure Message Broker

Add RabbitMQ configuration to your base YAML files:
spring:
  rabbitmq:
    host: ${RABBITMQ_HOST:localhost}
    port: ${RABBITMQ_PORT:5672}
    username: ${RABBITMQ_USERNAME:guest}
    password: ${RABBITMQ_PASSWORD:guest}
3

Expose Bus Refresh Endpoint

Enable the bus-refresh endpoint on the Config Server:
management:
  endpoints:
    web:
      exposure:
        include: health, info, bus-refresh
4

Trigger Broadcast Refresh

Send a single refresh event that propagates to all services:
curl -X POST http://localhost:8888/actuator/bus-refresh
With Spring Cloud Bus, you only need to call one endpoint to refresh all connected services.

What Can Be Refreshed?

Refreshable Configuration

Beans annotated with @RefreshScope can be reloaded:
@Component
@RefreshScope
public class ServiceConfiguration {
    @Value("${service.timeout}")
    private int timeout;
    
    @Value("${service.retry.attempts}")
    private int retryAttempts;
}
Typical refreshable properties:
  • Feature flags
  • Timeouts and retry settings
  • API endpoint URLs
  • Logging levels (with some limitations)
  • Rate limiting thresholds
  • Caching TTL values

Non-Refreshable Configuration

The following configuration types cannot be refreshed without a restart:
  • Server port (server.port)
  • Eureka instance configuration (hostname, instance ID)
  • Database connection pools (URL, username, password)
  • OAuth2 client registration (client ID, secret, scopes)
  • JWT keystore settings (location, passwords)
  • Spring Session store type (Redis vs JDBC)

When to Use Refresh vs Restart

Use Refresh For

Feature Toggles

Enable or disable features without downtime.

Operational Tuning

Adjust timeouts, retries, or rate limits.

URL Changes

Update downstream service URLs.

Log Levels

Increase logging detail for debugging.

Requires Restart

Security Changes

OAuth2 configuration, keystore paths, credentials.

Database Settings

Connection strings, pool sizes, drivers.

Server Configuration

Port numbers, SSL settings, context paths.

Discovery Changes

Eureka client settings, instance metadata.

Step-by-Step Refresh Guide

Scenario: Update Zipkin Sampling Rate

Let’s walk through updating the distributed tracing sampling rate from 10% to 50%:
1

Identify the Configuration

Current configuration in sgivu-auth.yml:
management:
  tracing:
    sampling:
      probability: 0.1
2

Update and Commit

cd ~/workspace/source

# Edit the file
sed -i 's/probability: 0.1/probability: 0.5/' sgivu-auth.yml

# Commit to Git
git add sgivu-auth.yml
git commit -m "Increase Zipkin sampling to 50% for debugging"
git push
3

Verify Config Server

Check that Config Server sees the change:
curl http://localhost:8888/sgivu-auth/dev | grep probability
Should output:
"management.tracing.sampling.probability": 0.5
4

Refresh the Service

curl -X POST http://localhost:9000/actuator/refresh
Response:
[
  "management.tracing.sampling.probability"
]
5

Confirm the Change

The auth service now traces 50% of requests. Check Zipkin for increased trace volume.

Refresh in Production

Best Practices

Test First

Always test configuration changes in dev before production.

Rolling Refresh

Refresh one instance at a time in multi-instance deployments.

Monitor Impact

Watch metrics and logs after refresh to catch issues early.

Document Changes

Record what was changed and why in commit messages.

Security Considerations

Restrict access to refresh endpoints in production:
management:
  endpoints:
    web:
      exposure:
        include: health, info, refresh
  endpoint:
    refresh:
      enabled: true
spring:
  security:
    user:
      name: ${ACTUATOR_USERNAME}
      password: ${ACTUATOR_PASSWORD}
Then use authentication when calling the endpoint:
curl -u admin:secret -X POST http://prod-service:8080/actuator/refresh

Limitations and Considerations

Refresh Limitations

  1. Beans must be @RefreshScope - Only annotated beans are reloaded
  2. State is lost - In-memory state in refreshed beans is reset
  3. No atomic updates - Each service refreshes independently
  4. Connection pools persist - Database/Redis connections aren’t recreated
  5. Scheduled tasks continue - @Scheduled methods use old config until next execution

When Things Go Wrong

Cause: No configuration actually changed, or the properties aren’t in @RefreshScope beans.Solution: Verify the property path is correct and that beans consuming it are annotated.
Cause: Configuration is cached or used at startup only.Solution: Check if the property requires a restart. Consider using @RefreshScope on relevant beans.
Cause: Endpoint is not exposed in management.endpoints.web.exposure.include.Solution: Add refresh to the include list and restart the service once.
Cause: Config Server may be caching or hasn’t pulled latest commits.Solution: Restart Config Server or configure webhook-based refresh.

Automating Refresh with Git Webhooks

For advanced setups, configure Git webhooks to automatically trigger refresh when config changes:
# GitHub webhook example
# POST to: http://config-server:8888/monitor
# Payload: Git push event

# Config Server automatically:
# 1. Detects which services are affected
# 2. Publishes refresh event to Spring Cloud Bus
# 3. All services refresh automatically
This requires the spring-cloud-config-monitor dependency and a message bus (RabbitMQ/Kafka).

Monitoring

Monitor services after configuration refresh

Validation

Validate configuration before refresh

Security

Secure refresh endpoints in production

Testing Changes

Test configuration changes locally

Build docs developers (and LLMs) love