Distributed Config Centers Compared: Spring Cloud Config, Apollo, Nacos, Consul, Etcd
Explore the evolution of configuration management and get an in‑depth comparison of five leading distributed configuration centers—Spring Cloud Config, Apollo, Nacos, Consul, and Etcd—covering architecture, core implementation, advantages, drawbacks, and practical selection guidance for modern backend and cloud‑native applications.
Preface
Recently a colleague asked which distributed configuration center is the best. This article introduces the five most commonly used configuration centers and helps you choose the right one.
1. Evolution of Configuration Centers
Three Eras of Configuration Management
1.0 Era: Hard‑coded Configuration
// Ancient configuration management
public class DatabaseConfig {
private static final String URL = "jdbc:mysql://localhost:3306/app";
private static final String USERNAME = "root";
private static final String PASSWORD = "123456";
public Connection getConnection() {
// Every change requires recompilation and redeployment
return DriverManager.getConnection(URL, USERNAME, PASSWORD);
}
}2.0 Era: External Configuration Files
# application.properties
db.url=jdbc:mysql://localhost:3306/app
db.username=root
db.password=123456 @Configuration
public class DatabaseConfig {
@Value("${db.url}")
private String url;
@Value("${db.username}")
private String username;
@Value("${db.password}")
private String password;
// Changes still require application restart
}3.0 Era: Configuration Center
@Configuration
public class DynamicDatabaseConfig {
@Autowired
private ConfigService configService;
@Bean
@RefreshScope
public DataSource dataSource() {
String url = configService.getProperty("db.url");
String username = configService.getProperty("db.username");
String password = configService.getProperty("db.password");
return DataSourceBuilder.create().url(url).username(username).password(password).build();
}
}Why a Configuration Center?
Configuration centers provide unified management, dynamic updates without restarts, version control, permission control, and environment isolation.
Unified Management: All configurations are stored centrally.
Dynamic Updates: Changes are pushed to applications in real time.
Version Control: History tracking and rollback.
Permission Control: Access control for sensitive configs.
Environment Isolation: Separate configs per environment.
2. Spring Cloud Config – Native Choice for the Spring Ecosystem
Architecture
Core Implementation
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
@Configuration
public class ConfigServerConfig {
@Bean
public MultipleJGitEnvironmentRepository multipleJGitEnvironmentRepository() {
MultipleJGitEnvironmentRepository repository = new MultipleJGitEnvironmentRepository();
Map<String, PatternMatchingJGitEnvironmentRepository> repos = new HashMap<>();
repos.put("service-.*", createGitRepo("https://github.com/config/service-config"));
repos.put("user-.*", createGitRepo("https://github.com/config/user-config"));
repository.setRepos(repos);
return repository;
}
private PatternMatchingJGitEnvironmentRepository createGitRepo(String uri) {
PatternMatchingJGitEnvironmentRepository repo = new PatternMatchingJGitEnvironmentRepository();
repo.setUri(uri);
repo.setBasedir("/tmp/config-repo");
return repo;
}
} @SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
@Configuration
@RefreshScope
public class ApplicationConfig {
@Value("${app.database.url:jdbc:mysql://localhost:3306/default}")
private String databaseUrl;
@Value("${app.redis.host:localhost}")
private String redisHost;
@EventListener
public void handleRefresh(EnvironmentChangeEvent event) {
System.out.println("Configuration changed: " + event.getKeys());
refreshDataSource();
}
private void refreshDataSource() {
// Rebuild datasource dynamically
}
@PostMapping("/refresh")
public String refresh() {
return "Configuration refreshed";
}
}Advantages
Seamless integration with Spring ecosystem.
Supports multiple backends (Git, SVN, local files).
Configuration versioning.
Encryption support.
Disadvantages
Changes require manual refresh or Git webhook.
Long‑polling leads to slower real‑time performance.
Lacks a friendly management UI.
High‑availability setup is relatively complex.
3. Apollo – Ctrip’s Enterprise‑Grade Configuration Center
Architecture
Core Implementation
@Configuration
public class ApolloClientConfig {
@Bean
public Config config() {
System.setProperty("apollo.meta", "http://apollo-config:8080");
Config appConfig = ConfigService.getAppConfig();
appConfig.addChangeListener(changeEvent -> {
for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key);
System.out.println(String.format("Config changed - key: %s, old: %s, new: %s, type: %s", change.getPropertyName(), change.getOldValue(), change.getNewValue(), change.getChangeType()));
handleConfigChange(change);
}
});
return appConfig;
}
private void handleConfigChange(ConfigChange change) {
switch (change.getPropertyName()) {
case "app.database.url":
refreshDataSource();
break;
case "app.redis.host":
refreshRedisConnection();
break;
case "app.feature.toggle":
updateFeatureToggle();
break;
}
}
// Additional methods omitted for brevity
}Advantages
Real‑time push within one second.
Comprehensive permission management and audit.
Supports multiple environments, clusters, and namespaces.
User‑friendly UI.
Client‑side caching for high availability.
Disadvantages
Deployment is relatively complex.
Depends on external storage such as MySQL.
Higher client memory consumption.
4. Nacos – Alibaba’s Dynamic Service Discovery & Configuration Management
Architecture
Core Implementation
@SpringBootApplication
@EnableDiscoveryClient
public class NacosApplication {
public static void main(String[] args) {
SpringApplication.run(NacosApplication.class, args);
}
}
@Configuration
@NacosPropertySource(dataId = "user-service", autoRefreshed = true)
public class NacosConfig {
@NacosValue(value = "${app.database.url:jdbc:mysql://localhost:3306/default}", autoRefreshed = true)
private String databaseUrl;
@NacosValue(value = "${app.thread.pool.size:10}", autoRefreshed = true)
private int threadPoolSize;
@NacosConfigListener(dataId = "user-service")
public void onConfigChange(String newConfig) {
System.out.println("Config changed: " + newConfig);
applyNewConfig(parseConfig(newConfig));
}
}Advantages
Real‑time configuration push.
Good integration with Spring Cloud.
Supports multiple environments and clusters.
Provides a friendly management console.
Lightweight and easy to deploy.
Disadvantages
Management UI is relatively simple.
Permission management is weaker.
Performance at massive scale still needs verification.
5. Consul – HashiCorp’s Service‑Mesh‑Ready Configuration Center
Architecture
Core Implementation
@Configuration
public class ConsulConfig {
@Bean
public ConsulClient consulClient() {
return new ConsulClient("localhost", 8500);
}
@Bean
public ConfigPropertySourceLocator configPropertySourceLocator() {
return new ConsulConfigPropertySourceLocator(consulClient());
}
}
@Component
public class ConsulConfigWatcher {
@Autowired
private ConsulClient consulClient;
private final Map<String, List<Consumer<String>>> watchers = new ConcurrentHashMap<>();
@PostConstruct
public void init() {
watchConfig("config/app/database");
watchConfig("config/app/redis");
watchConfig("config/app/features");
}
private void watchConfig(String key) {
new Thread(() -> {
while (true) {
try {
Response<GetValue> response = consulClient.getKVValue(key);
if (response.getValue() != null) {
String config = response.getValue().getDecodedValue();
notifyWatchers(key, config);
}
long lastIndex = response.getConsulIndex();
response = consulClient.getKVValue(key, new QueryParams(BlockingMode.SOURCE, 60000, lastIndex));
} catch (Exception e) {
System.err.println("Watch failed: " + e.getMessage());
try { Thread.sleep(5000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); break; }
}
}
}).start();
}
public void registerWatcher(String key, Consumer<String> watcher) {
watchers.computeIfAbsent(key, k -> new ArrayList<>()).add(watcher);
}
private void notifyWatchers(String key, String config) {
List<Consumer<String>> keyWatchers = watchers.get(key);
if (keyWatchers != null) {
keyWatchers.forEach(w -> w.accept(config));
}
}
}Advantages
Full service‑mesh solution.
Multi‑data‑center support.
Strong consistency and high availability.
Health checks and fault recovery.
Rich ACL and security features.
Disadvantages
Higher resource consumption.
Complex deployment and operation.
Steep learning curve.
Client integration can be cumbersome.
6. Etcd – Kubernetes‑Native Key‑Value Store
Architecture
Core Implementation
@Configuration
public class EtcdConfig {
@Bean
public Client etcdClient() {
return Client.builder()
.endpoints("http://etcd1:2379", "http://etcd2:2379", "http://etcd3:2379")
.build();
}
@Bean
public KV etcdKV() {
return etcdClient().getKVClient();
}
@Bean
public Watch etcdWatch() {
return etcdClient().getWatchClient();
}
}
@Service
public class EtcdConfigManager {
@Autowired
private KV etcdKV;
@Autowired
private Watch etcdWatch;
private final Map<String, List<Consumer<String>>> configWatchers = new ConcurrentHashMap<>();
public void saveConfig(String key, String value) {
ByteSequence etcdKey = ByteSequence.from(key.getBytes());
ByteSequence etcdValue = ByteSequence.from(value.getBytes());
etcdKV.put(etcdKey, etcdValue).join();
}
public String getConfig(String key) {
ByteSequence etcdKey = ByteSequence.from(key.getBytes());
GetResponse response = etcdKV.get(etcdKey).join();
if (response.getKvs().isEmpty()) return null;
return response.getKvs().get(0).getValue().toString();
}
public void watchConfig(String key) {
ByteSequence etcdKey = ByteSequence.from(key.getBytes());
etcdWatch.watch(etcdKey, new Watch.Listener() {
@Override
public void onNext(WatchResponse response) {
for (WatchEvent event : response.getEvents()) {
if (event.getEventType() == WatchEvent.EventType.PUT) {
String newValue = event.getKeyValue().getValue().toString();
notifyWatchers(key, newValue);
}
}
}
@Override
public void onError(Throwable throwable) {
System.err.println("Watch error: " + throwable.getMessage());
}
@Override
public void onCompleted() {
System.out.println("Watch completed");
}
});
}
private void notifyWatchers(String key, String config) {
List<Consumer<String>> keyWatchers = configWatchers.get(key);
if (keyWatchers != null) {
keyWatchers.forEach(w -> w.accept(config));
}
}
// Distributed lock example omitted for brevity
}Advantages
High performance, low latency.
Strong consistency guarantees.
Native integration with Kubernetes.
Simple API design.
Reliable distributed lock support.
Disadvantages
Feature set is relatively simple.
No friendly management UI.
Client ecosystem is smaller.
Operational complexity can be high.
7. Comparison of the Five Config Centers
The table below summarizes key dimensions. In practice, choose based on real‑time push, permission needs, versioning, service discovery, UI, deployment complexity, and ecosystem fit.
Real‑time Push: Apollo, Nacos, Consul, Etcd provide real‑time updates; Spring Cloud Config requires manual refresh.
Configuration Formats: Spring Cloud Config, Apollo, Nacos support multiple formats; Consul and Etcd are key‑value stores.
Permission Management: Apollo and Consul have mature ACLs; others are basic.
Version Management: Spring Cloud Config uses Git; Apollo offers built‑in versioning; others provide basic support.
Service Discovery: Nacos, Consul, Etcd include discovery; Spring Cloud Config needs Eureka; Apollo does not.
Management UI: Apollo, Nacos, Consul have UIs; Spring Cloud Config and Etcd do not.
Deployment Complexity: Spring Cloud Config is simple; Apollo and Consul are more complex; Nacos and Etcd are moderate.
Ecosystem Integration: Spring Cloud Config fits Spring Cloud; Nacos fits Spring Cloud Alibaba; Consul fits HashiCorp; Etcd fits Kubernetes.
Selection Guide
When to Choose Spring Cloud Config
Already using the Spring Cloud stack.
Team is comfortable with Git workflows.
Configuration real‑time requirements are low.
Desire minimal external dependencies.
When to Choose Apollo
Enterprise‑grade applications need comprehensive permission management.
Frequent configuration changes require instant effect.
Multi‑environment and multi‑cluster management is required.
Need a user‑friendly management console.
When to Choose Nacos
Need unified configuration and service discovery.
Using the Spring Cloud Alibaba stack.
Prefer simpler deployment and maintenance.
Permission management requirements are modest.
When to Choose Consul
Require a full service‑mesh solution.
Multi‑data‑center deployment.
Strong consistency and high availability are critical.
Need rich security and ACL features.
When to Choose Etcd
Operating in a Kubernetes environment.
High performance and low latency are essential.
Strong consistency guarantees are required.
Configuration needs are relatively simple.
Practical Scenario Recommendations
Scenario 1: Traditional Enterprise Microservice Refactor
Recommendation: Spring Cloud Config + Eureka
Reason: Unified tech stack, low learning curve, seamless Spring integration.Scenario 2: Large‑scale E‑commerce Platform
Recommendation: Apollo
Reason: Frequent config changes, comprehensive permission audit, multi‑environment management.Scenario 3: Cloud‑Native Stack
Recommendation: Nacos or Consul
Reason: Integrated service discovery and config management, cloud‑native friendly.Scenario 4: Kubernetes‑Based Deployment
Recommendation: Etcd (Kubernetes built‑in) + optional Nacos for application configs
Reason: Separate infrastructure config (Etcd) from application config (Nacos) for clear responsibilities.Conclusion
When selecting a configuration center, consider the following key factors:
Technology Stack Fit: Choose the solution that aligns best with your team’s stack.
Feature Requirements: Match the functional set to your actual configuration management needs.
Operational Cost: Evaluate deployment, monitoring, and maintenance complexity.
Ecosystem Support: Prefer projects with active communities and solid ecosystem.
Long‑Term Evolution: Consider the roadmap and future development of the technology.
Remember, there is no universally best configuration center—only the one that best fits your specific scenario.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Su San Talks Tech
Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
