Course topics

By WebNest Studio

Spring Boot Tutorial

Centralized Configuration with Spring Cloud Config

With ten services in three environments, you have thirty sets of configuration. Changing a shared setting — a feature flag, a timeout, a third-party URL — should not require editing and redeploying every service. Spring Cloud Config provides a central configuration server backed by a Git repository (or Vault, a database, or the file system): every service fetches its configuration from it at startup, and changes are versioned and reviewable like code.

This lesson builds a Config Server, organises configuration per application and profile, connects client services with spring.config.import, encrypts secrets, and refreshes configuration without restarting.

How It Works

The Config Server is a Spring Boot application with @EnableConfigServer. It serves properties over HTTP at /{application}/{profile}/{label}, reading files from a Git repository: application.yml (shared by all services), order-service.yml (one service), order-service-prod.yml (one service in one profile). The label is a Git branch or tag, so you can pin configuration versions.

Connecting Clients

Client services add spring-cloud-starter-config and a single line: spring.config.import=optional:configserver:http://config-server:8888. The service's spring.application.name and active profiles determine which files it receives. Remote properties take precedence over the service's local application.yml. Use spring.cloud.config.fail-fast=true with retry in production so services do not start with missing configuration.

Secrets

Never store plain-text secrets in the Git repository. Options: encrypt values with the Config Server's /encrypt endpoint and store {cipher}... strings (decrypted when served); use the Vault backend; or keep secrets entirely out of Config and inject them from the platform (Kubernetes Secrets, a cloud secret manager). Secure the Config Server itself with authentication and network restrictions.

Refreshing Configuration at Runtime

Beans annotated with @RefreshScope — and all @ConfigurationProperties beans — are rebuilt when a refresh happens. Trigger it per instance with POST /actuator/refresh, or for all instances at once with Spring Cloud Bus (over Kafka or RabbitMQ) and a Git webhook. Reserve runtime refresh for values that are safe to change live, such as feature flags and limits.

On Kubernetes

If you deploy on Kubernetes, ConfigMaps and Secrets (optionally via Spring Cloud Kubernetes) may make a separate Config Server unnecessary. Config Server remains attractive for Git-reviewed configuration shared across many services and environments, especially outside Kubernetes.

Examples

The Config Server

Java
<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/webnest/shop-config
          default-label: main
          search-paths: '{application}'
          username: ${CONFIG_GIT_USER}
          password: ${CONFIG_GIT_TOKEN}
Output
Started ConfigServerApplication on port 8888

curl http://localhost:8888/order-service/prod
{"name":"order-service","profiles":["prod"],"label":"main","version":"a41f9c2...",
 "propertySources":[
   {"name":"https://github.com/webnest/shop-config/order-service/order-service-prod.yml","source":{"orders.max-items":"50"}},
   {"name":".../order-service/order-service.yml","source":{"orders.max-items":"20","orders.currency":"INR"}},
   {"name":".../application.yml","source":{"management.endpoints.web.exposure.include":"health,prometheus"}}]}

Configuration repository layout

Java
shop-config/  (Git repository)
├── application.yml                      # shared by every service
├── order-service/
│   ├── order-service.yml                # all profiles
│   └── order-service-prod.yml           # prod overrides
└── payment-service/
    └── payment-service.yml

# order-service/order-service.yml
orders:
  max-items: 20
  currency: INR
features:
  new-checkout: false

# order-service/order-service-prod.yml
orders:
  max-items: 50
payments:
  api-key: '{cipher}AQA3n2k...9fZ'       # encrypted with the server's key
Output
(Every change is a Git commit with author, review and history.)

A client service with refreshable properties

Java
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

# order-service application.yml
spring:
  application:
    name: order-service
  config:
    import: optional:configserver:http://localhost:8888
  cloud:
    config:
      fail-fast: true
management:
  endpoints:
    web:
      exposure:
        include: health, refresh

@ConfigurationProperties(prefix = "features")
public record FeatureFlags(boolean newCheckout) {}

@RestController
public class CheckoutController {
    private final FeatureFlags flags;
    public CheckoutController(FeatureFlags flags) { this.flags = flags; }

    @GetMapping("/api/checkout/version")
    public String version() {
        return flags.newCheckout() ? "new checkout" : "classic checkout";
    }
}
Output
GET /api/checkout/version -> classic checkout
(commit features.new-checkout: true to the config repo)
POST /actuator/refresh    -> ["features.new-checkout"]
GET /api/checkout/version -> new checkout      (no restart)

Common Mistakes

  • Committing plain-text passwords to the configuration repository.
  • Leaving the Config Server open without authentication on the network.
  • Not enabling fail-fast, so services start with default values when the Config Server is unreachable.
  • Refreshing configuration that is not safe to change at runtime (datasource URLs, thread pools).
  • Duplicating the same property in many service files instead of the shared application.yml.

Key Points to Remember

  • @EnableConfigServer serves versioned configuration from Git per application, profile and label.
  • Clients connect with spring.config.import=configserver:... and spring.application.name.
  • Encrypt secrets ({cipher}) or keep them in Vault/platform secrets.
  • @RefreshScope and @ConfigurationProperties beans update on /actuator/refresh or via Spring Cloud Bus.
  • On Kubernetes, ConfigMaps/Secrets may replace a separate Config Server.

Practice the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.

Use your local JDK or project IDE for these examples. Codelab currently runs Python and HTML/CSS/JavaScript; framework examples may need project dependencies.