Config Server

One Place to Manage All Your Microservices Configuration

The Problem

You have 20 microservices. Each has its own application.yml with database URLs, API keys, feature flags. Now you need to change the database password. Update 20 files? Redeploy 20 services? What if you miss one?

Config Server centralizes all configuration. Change once, all services pick it up.

// WITHOUT Config Server
user-service/application.yml    → db.url=jdbc:mysql://old-db:3306
order-service/application.yml   → db.url=jdbc:mysql://old-db:3306
payment-service/application.yml → db.url=jdbc:mysql://old-db:3306
// Change all 20 manually...

// WITH Config Server
config-repo/application.yml → db.url=jdbc:mysql://new-db:3306
// All services automatically get the new value!

Single Source of Truth

All configuration in one Git repository.

Environment Specific

Different values for dev, staging, production.

Dynamic Updates

Change config without redeploying services.

Config Server Setup

<!-- pom.xml for 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 for Config Server
server:
  port: 8888

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/your-org/config-repo
          default-label: main
          search-paths: '{application}'  # Optional: folder per service

Config Repository Structure

config-repo/
├── application.yml          # Shared by ALL services
├── application-dev.yml      # Shared dev config
├── application-prod.yml     # Shared prod config
├── user-service.yml         # Specific to user-service
├── user-service-dev.yml     # user-service dev overrides
├── user-service-prod.yml    # user-service prod overrides
├── order-service.yml
└── payment-service.yml
# application.yml (shared)
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver

logging:
  level:
    root: INFO

# user-service.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/users

user:
  default-role: USER
  max-login-attempts: 5

# user-service-prod.yml
spring:
  datasource:
    url: jdbc:mysql://prod-db.example.com:3306/users

user:
  max-login-attempts: 3

Config Client Setup

<!-- pom.xml for any microservice -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
# application.yml for user-service
spring:
  application:
    name: user-service  # Must match filename in config repo
  profiles:
    active: dev
  config:
    import: optional:configserver:http://localhost:8888

# Service starts → Fetches user-service.yml + user-service-dev.yml

Accessing Configuration

@RestController
public class UserController {

    @Value("${user.default-role}")
    private String defaultRole;

    @Value("${user.max-login-attempts}")
    private int maxLoginAttempts;

    // Or use @ConfigurationProperties for groups
}

@ConfigurationProperties(prefix = "user")
@Component
public class UserProperties {
    private String defaultRole;
    private int maxLoginAttempts;
    // getters, setters
}

You can also fetch config directly from Config Server:

# Get user-service config for dev profile
GET http://localhost:8888/user-service/dev

# Response (JSON):
{
  "name": "user-service",
  "profiles": ["dev"],
  "propertySources": [
    {
      "name": "user-service-dev.yml",
      "source": {
        "user.default-role": "USER",
        "user.max-login-attempts": 5
      }
    }
  ]
}

Dynamic Refresh

Change config without restart using Spring Cloud Bus:

<!-- Add to services -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
# application.yml
management:
  endpoints:
    web:
      exposure:
        include: refresh, busrefresh

spring:
  rabbitmq:
    host: localhost
    port: 5672
# After changing config in Git:
# Refresh single service
POST http://localhost:8080/actuator/refresh

# Refresh ALL services via message bus
POST http://localhost:8080/actuator/busrefresh
// Mark beans that should refresh
@RefreshScope
@Component
public class UserProperties {
    @Value("${user.max-login-attempts}")
    private int maxLoginAttempts;
    // Will update when /refresh is called
}

Encrypting Secrets

# Config Server application.yml
encrypt:
  key: my-secret-encryption-key  # Or use keystore

# In config repo - store encrypted values:
spring:
  datasource:
    password: '{cipher}AQB+...encrypted...'

# Config Server decrypts before sending to clients
# Encrypt a value
POST http://localhost:8888/encrypt
Body: my-secret-password
→ Returns: AQB+...encrypted...

# Decrypt a value
POST http://localhost:8888/decrypt
Body: AQB+...encrypted...
→ Returns: my-secret-password

High Availability

# Run multiple Config Server instances behind load balancer
# Clients can specify multiple servers:

spring:
  config:
    import: >
      optional:configserver:http://config1:8888,
      optional:configserver:http://config2:8888

# With Eureka (recommended):
spring:
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config-server

Vault Integration

For sensitive secrets, use HashiCorp Vault instead of Git:

spring:
  cloud:
    config:
      server:
        vault:
          host: vault.example.com
          port: 8200
          scheme: https
          authentication: TOKEN
          token: ${VAULT_TOKEN}

Best Practices

  • Use Git: Version control your configuration with history
  • Encrypt secrets: Never store passwords in plain text
  • Separate environments: Different branches or folders for dev/prod
  • Use profiles: application-{profile}.yml for environment-specific config
  • Cache config: Clients should cache and handle Config Server downtime
  • Monitor changes: Track who changed what and when

Master Cloud-Native Architecture

Learn configuration management, service discovery, and more.

Explore Full Stack Java Course