Skip to content
Spring Boot sb microservices 3 min read

Config Server

When you run twenty services across three environments, copying property files everywhere is unmanageable. Spring Cloud Config Server centralizes configuration in one place — typically a git repository — and serves it to every service at startup, with runtime refresh and encryption built in. This page builds a server and wires up a client.

Why a config server

  • Single source of truth. All configuration lives in one versioned repository.
  • Audit and rollback. Git history shows who changed what, and reverting is a git revert.
  • Environment overlays. Per-profile files (-dev, -prod) layer cleanly.
  • Refresh without redeploy. Change config and refresh running services in place.
   git repo (config)


┌───────────────────┐    spring.config.import
│   Config Server    │◄──────────────────────── orders-service
│ @EnableConfigServer│◄──────────────────────── inventory-service
└───────────────────┘◄──────────────────────── payments-service

The config server

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}
# application.yml
server:
  port: 8888
spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/acme/config-repo
          default-label: main
          search-paths: '{application}'    # optional per-service subfolders

The git repository layout

The server maps requests to files by application name and profile:

config-repo/
├── application.yml              # shared defaults for ALL services
├── orders-service.yml           # orders, all profiles
├── orders-service-dev.yml       # orders, dev profile
└── inventory-service.yml

A client named orders-service running with profile dev receives application.yml + orders-service.yml + orders-service-dev.yml, merged with the most specific winning. You can verify directly over HTTP:

curl http://localhost:8888/orders-service/dev

Output:

{
  "name": "orders-service",
  "profiles": ["dev"],
  "label": "main",
  "propertySources": [
    { "name": "...orders-service-dev.yml", "source": { "server.port": 8081 } },
    { "name": "...orders-service.yml",     "source": { "feature.flag": true } }
  ]
}

The client

Add the config client starter and tell Boot to import config from the server. As of Spring Boot 2.4+, the modern mechanism is spring.config.import, not the old bootstrap context.

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
# orders-service application.yml
spring:
  application:
    name: orders-service                 # must match the file name in the repo
  config:
    import: "configserver:http://localhost:8888"
  profiles:
    active: dev

Note: The application name is what selects the right config file, so set spring.application.name correctly. To fail fast if the server is unreachable, use import: "configserver:..." (no optional: prefix).

Runtime refresh

Beans annotated with @RefreshScope are recreated when configuration changes — no restart needed.

@RestController
@RefreshScope
public class FeatureController {

    @Value("${feature.flag:false}")
    private boolean featureFlag;

    @GetMapping("/feature")
    public boolean feature() { return featureFlag; }
}

Expose and trigger the Actuator refresh endpoint:

management:
  endpoints:
    web:
      exposure:
        include: refresh
# after committing a change to the config repo:
curl -X POST http://localhost:8081/actuator/refresh

Output:

["feature.flag"]

The response lists the property keys that changed. For fleet-wide refresh without hitting each instance, add Spring Cloud Bus (spring-cloud-starter-bus-amqp) so a single /actuator/busrefresh broadcasts the change over RabbitMQ or Kafka.

Encryption

Never commit plaintext secrets. The config server can decrypt values on the way out so clients only ever see clear text in memory.

# config server — symmetric key (use an asymmetric keystore in production)
encrypt:
  key: ${ENCRYPT_KEY}
# encrypt a secret via the server's endpoint
curl http://localhost:8888/encrypt -d 's3cr3t-db-password'
# → a long cipher string

Store the cipher in the repo prefixed with {cipher}:

spring:
  datasource:
    password: '{cipher}AQB3f8...redacted...'

Tip: For real deployments prefer a dedicated secrets manager (HashiCorp Vault via spring-cloud-starter-vault-config, or your cloud provider’s secret store) over committing even encrypted secrets to git.

Last updated June 13, 2026
Was this helpful?