Skip to main content

Command Palette

Search for a command to run...

Spring Cloud Config Server Explained: Centralized Configuration for Scalable Microservices

Learn how Spring Cloud Config Server centralizes configuration, manages multiple environments, resolves property conflicts, and enables dynamic configuration updates across microservices.

Updated
5 min read
Spring Cloud Config Server Explained: Centralized Configuration for Scalable Microservices
A
I’m learning to think like a backend engineer — not just code like one. Focused on Java backend, AWS, and system design, I’m deeply interested in how scalable systems are built, how cloud infrastructure powers them, and how engineering decisions impact performance and reliability. I don’t just learn — I build, experiment, break things, and learn again. That’s how I grow. I believe curiosity, consistency, and learning from mistakes are what shape great engineers. Open to collaborations, real-world projects, and opportunities where I can build, contribute, and grow with like-minded people. This is my journey of becoming better every single day 🚀

Service Discovery Solved One Problem: Configuration Created Another

Modern microservice architectures solve many problems that monolithic applications struggle with. Technologies like Eureka Service Discovery, Feign Clients, and API Gateways make service-to-service communication seamless.

But as the number of services grows, a new challenge emerges:

Where should configuration live?

Managing configurations across dozens of microservices and environments quickly becomes difficult. This is exactly the problem that Spring Cloud Config Server was designed to solve.

Why Do We Need a Config Server?

Consider three simple microservices:

User Service

server:
  port: 8081

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/userdb

Hotel Service

server:
  port: 8082

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/hoteldb

Rating Service

server:
  port: 8083

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/ratingdb

At first, everything seems manageable.

Real-world applications rarely operate in a single environment.

Challenge 1: Multiple Environments

Enterprise applications typically run across:

DEV -- QA -- UAT -- STAGE -- PROD

Every microservice now requires environment-specific configurations:

user-service-dev.yml
user-service-qa.yml
user-service-prod.yml

hotel-service-dev.yml
hotel-service-qa.yml
hotel-service-prod.yml

rating-service-dev.yml
rating-service-qa.yml
rating-service-prod.yml

Even with just three services, configuration files begin to multiply rapidly.

Challenge 2: Configuration Changes

Imagine the database endpoint changes.

Before

spring:
  datasource:
    url: jdbc:mysql://old-db:3306/userdb

After

spring:
  datasource:
    url: jdbc:mysql://new-db:3306/userdb

Now the update must be applied across every service that uses the database.

In a system with dozens of microservices, this becomes error-prone and difficult to manage.

Challenge 3: Redeployment Overhead

Suppose a JWT secret changes:

jwt:
  secret: new-secret

Without centralized configuration, every service must:

Modify application.yml
Rebuild JAR
Redeploy Application

A simple configuration update suddenly becomes an operational task.

Challenge 4: Configuration Sprawl

In a large system with 50+ microservices:

service-a/application.yml
service-b/application.yml
service-c/application.yml
...

Finding, updating, and auditing configuration becomes increasingly difficult.

The Spring Cloud Config Solution

Instead of storing configuration inside each microservice:

Service
 └── application.yml

We centralize everything:

The Config Server becomes the single source of truth for all application configurations.

Why Git Is Used as the Configuration Store

Spring Cloud Config integrates naturally with Git because Git already provides:

Version Control, History Tracking, Rollback Support, Audit Trail, Branching Strategy

Example repository:

This allows infrastructure and configuration to follow the same versioning practices as source code.

How Configuration Fetching Works

When a microservice starts:

Step 1: User Service launches.

Step 2: It contacts Config Server.

Step 3: Requests configuration:

GET /user-service/dev

Step 4: Config Server retrieves:

user-service-dev.yml

from Git.

Step 5: Returns configuration:

server:
  port: 8081

jwt:
  secret: secret123

Step 6: The service starts using those values.

Bootstrap Configuration

A common question is:

How does a service know where the Config Server is before startup?

The answer is a minimal local configuration:

spring:
  config:
    import: configserver:http://localhost:8888

This instructs Spring Boot:

Before application startup,
fetch configuration from Config Server.

Building a Config Server

Dependency

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

Main Class

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(
                ConfigServerApplication.class,
                args
        );
    }
}

Configuration

server:
  port: 8888

spring:
  application:
    name: CONFIG-SERVER

  cloud:
    config:
      server:
        git:
          uri: https://github.com/your-org/config-repo

Once started, the Config Server acts as a bridge between Git and all microservices.

Understanding Property Resolution Priority

One of the most important concepts in Spring Cloud Config is understanding what happens when the same property exists in multiple files.

Spring does not choose a single file. It merges them

The property resolution order is:

application.yml
        ↓
application-{profile}.yml
        ↓
{service-name}.yml
        ↓
{service-name}-{profile}.yml

The more specific the file, the higher its priority.

Multiple Active Profiles

Spring also supports multiple profiles.

spring:
  profiles:
    active: dev,mysql

Files loaded:

user-service.yml
user-service-dev.yml
user-service-mysql.yml

If both define the same property:

user-service-dev.yml

database:
  host: localhost

user-service-mysql.yml

database:
  host: mysql-container

Final value:

database.host=mysql-container

because mysql is processed after dev.

Accessing Configurations in Code

Using @Value

@Value("${jwt.secret}")
private String jwtSecret;

Using ConfigurationProperties

@ConfigurationProperties(prefix = "jwt")
public class JwtProperties {
    private String secret;
}

The microservice uses the configuration exactly as if it were stored locally.

Dynamic Configuration Refresh

One of the most powerful features of Spring Cloud Config is runtime refresh.

Suppose Git changes:

jwt:
  secret: old

to

jwt:
  secret: new

Normally, a restart would be required.

Instead, use:

@RefreshScope
@Service
public class JwtService {
}

and trigger:

POST /actuator/refresh

Spring reloads updated configuration without restarting the application.

A scalable repository typically follows:

config-repo

application.yml
application-dev.yml
application-prod.yml

user-service.yml
user-service-dev.yml
user-service-prod.yml

hotel-service.yml
hotel-service-dev.yml
hotel-service-prod.yml

rating-service.yml
rating-service-dev.yml
rating-service-prod.yml

gateway.yml
gateway-prod.yml

This structure promotes:

  • Reusability

  • Environment isolation

  • Easier maintenance

  • Cleaner configuration management

Production Architecture

A typical production deployment looks like:

Each service retrieves configuration from Config Server while using Eureka for service discovery.

Interview Question

What is Refresh Scope?

Refresh Scope allows Spring beans to reload configuration changes at runtime without restarting the application.