Cloud Native 25 min read

Apollo vs Nacos: Which Configuration Center Is Truly Better?

This article analytically compares Apollo and Nacos—two leading configuration centers for microservices—by examining their design philosophies, setup procedures, core features, real‑time push mechanisms, data models, performance, operational overhead, and community support, ultimately offering guidance on selecting the most suitable solution for different project scenarios.

Su San Talks Tech
Su San Talks Tech
Su San Talks Tech
Apollo vs Nacos: Which Configuration Center Is Truly Better?

Design Philosophy

Nacos (Naming and Configuration Service) was open‑sourced by Alibaba in 2018 with the goal of providing a one‑stop platform for cloud‑native applications, offering both service discovery and configuration management. Its slogan is “a dynamic service discovery, configuration and management platform that makes building cloud‑native applications easier.”

Apollo originated from Ctrip in 2016 and has always focused solely on configuration management, addressing complex enterprise needs such as multi‑environment, multi‑cluster, fine‑grained permission control, and gray releases.

A simple analogy: Nacos is a Swiss‑army knife that can both cut (configuration) and open bottles (service discovery); Apollo is a premium chef’s knife that only cuts but does it exceptionally well.

Ease of Use

Nacos: Minimal Startup

# Download the latest Nacos Server
wget https://github.com/alibaba/nacos/releases/download/2.2.3/nacos-server-2.2.3.zip
unzip nacos-server-2.2.3.zip
cd nacos/bin
# Standalone mode (Linux/Mac)
sh startup.sh -m standalone
# Windows
startup.cmd -m standalone

After startup, visit http://localhost:8848/nacos (default username/password: nacos). Add the following Spring Boot dependencies:

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  <version>2021.0.5.0</version>
</dependency>
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  <version>2021.0.5.0</version>
</dependency>

Configure bootstrap.properties:

spring.application.name=my-service
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.file-extension=properties
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

Use the configuration in code:

@RestController
@RefreshScope
public class DemoController {
    @Value("${user.name:default}")
    private String userName;

    @GetMapping("/config")
    public String getConfig() {
        return "Current user name: " + userName;
    }

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/services")
    public List<String> services() {
        return discoveryClient.getServices();
    }
}

From download to a working configuration read, an experienced developer can finish in under ten minutes. Nacos’s integrated design lets configuration and discovery share the same server, and the client configuration is concise.

Apollo: Slightly More Complex Deployment

Apollo consists of four core components: ConfigService, AdminService, Portal, and MetaServer (Eureka‑based discovery).

# Download Quick Start package
wget https://github.com/apolloconfig/apollo-quick-start/releases/download/v2.1.0/apollo-quick-start-2.1.0.zip
unzip apollo-quick-start-2.1.0.zip
cd apollo-quick-start
# Execute script (starts MySQL and all services)
./demo.sh start

After startup, visit http://localhost:8070 (default username/password: apollo/admin). Add the Maven dependency:

<dependency>
  <groupId>com.ctrip.framework.apollo</groupId>
  <artifactId>apollo-client</artifactId>
  <version>2.1.0</version>
</dependency>

Configure application.properties:

app.id=my-service
apollo.meta=http://localhost:8080
apollo.bootstrap.enabled=true
apollo.bootstrap.namespaces=application

Use the configuration in code:

@Component
public class ApolloConfigBean {
    @Value("${user.name:default}")
    private String userName;

    public String getConfig(String key) {
        Config config = ConfigService.getAppConfig();
        return config.getProperty(key, "default");
    }

    @ApolloConfigChangeListener
    private void onChange(ConfigChangeEvent changeEvent) {
        for (String key : changeEvent.changedKeys()) {
            System.out.println(key + " changed!");
        }
    }
}

The Quick Start script automates many steps, but the need to start multiple components makes Apollo’s startup slightly slower and consumes more ports.

Core Features

Basic Configuration Management

Supported formats : Both support properties, yaml, xml, json. Nacos’s console allows direct YAML editing with syntax highlighting; Apollo displays key‑value pairs by default, making YAML editing less convenient.

Version management : Both keep historical versions and support rollback. Apollo’s granularity is finer, allowing per‑release comparison and detailed change view; Nacos offers a simpler versioning model.

Environment & cluster management : Apollo natively supports multiple environments (DEV, FAT, UAT, PRO) and clusters with complete isolation. Nacos achieves isolation via Namespace and Group, which requires a naming strategy and is less intuitive.

Example: In Apollo, creating a DEV configuration and a PRO configuration yields two completely independent items. In Nacos, you would create separate Namespace s.

Real‑time Configuration Push

Nacos Long‑Polling Mechanism

Nacos uses HTTP long‑polling. The client periodically sends a request containing the MD5 of the current configuration; the server returns immediately if there is a change, otherwise it holds the request (up to ~30 seconds) using AsyncContext and a scheduled timeout task.

// Core client long‑polling logic
public void start() {
    executor.scheduleWithFixedDelay(new LongPollingRunnable(), 0, retryInterval, TimeUnit.SECONDS);
}
class LongPollingRunnable implements Runnable {
    @Override
    public void run() {
        String listeningConfigs = buildListeningConfigs();
        Request request = new Request.Builder()
            .url(serverAddr + "/v1/cs/configs/listener")
            .post(body)
            .build();
        try (Response resp = httpClient.newCall(request).execute()) {
            if (resp.isSuccessful()) {
                String content = resp.body().string();
                if (StringUtils.isNotEmpty(content)) {
                    pullNewConfig(content);
                }
            }
        }
    }
}
// Server side handling
AsyncContext asyncContext = request.startAsync();
asyncContext.setTimeout(0); // disable container timeout
ClientSubscription sub = new ClientSubscription(keys, asyncContext);
subscribers.computeIfAbsent(key, k -> new CopyOnWriteArrayList<>()).add(sub);
ScheduledFuture<?> timeoutTask = scheduler.schedule(() -> {
    asyncContext.getResponse().getWriter().write("");
    asyncContext.complete();
}, 29500, TimeUnit.MILLISECONDS);

This design achieves near‑real‑time (second‑level) pushes while avoiding the resource cost of persistent WebSocket connections.

Apollo Timed‑Polling Mechanism

Apollo’s client polls every 60 seconds by default (configurable via apollo.refreshInterval). It uses Spring’s DeferredResult to implement asynchronous responses.

// Server side key method
@RequestMapping(method = RequestMethod.GET)
public DeferredResult<ResponseEntity<List<ApolloConfigNotification>>> pollNotification(
        @RequestParam("appId") String appId,
        @RequestParam("cluster") String cluster,
        @RequestParam("notifications") String notificationsAsString,
        @RequestParam(value = "dataCenter", required = false) String dataCenter,
        @RequestParam(value = "ip", required = false) String clientIp) {
    DeferredResult<ResponseEntity<List<ApolloConfigNotification>>> deferredResult =
        new DeferredResult<>(timeout);
    deferredResults.add(deferredResult);
    return deferredResult;
}

Comparison of the two mechanisms:

Push latency : Nacos – seconds (1‑2 s); Apollo – depends on polling interval, default 60 s.

Server load : Nacos – moderate (maintains a pending request queue); Apollo – lower (stateless).

Connection count : Nacos – proportional to client count; Apollo – proportional to polling frequency.

Penetration : Both work over plain HTTP.

If a business requires sub‑second configuration changes (e.g., flash‑sale switches), Nacos’s long‑polling gives an advantage; otherwise Apollo’s minute‑level delay is acceptable for most scenarios.

Gray Release & Permission Control

Apollo excels here. It supports gray releases by IP, machine, or user tag, allowing incremental rollout and full/gray rollback via a user‑friendly UI. Permission control is multi‑dimensional (application, environment, namespace) with audit logs that record who changed what and when.

In contrast, Nacos’s RBAC is more basic; gray release must be simulated with multiple Namespace s or groups, raising the entry barrier for many teams.

Service Discovery

Nacos provides built‑in service discovery (health checks, weight routing, etc.), effectively replacing Eureka or Consul. Apollo does not offer service discovery at all, so teams using Apollo must integrate a separate discovery solution.

@RestController
public class ConsumerController {
    @Autowired
    private LoadBalancerClient loadBalancerClient;
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/call")
    public String call() {
        ServiceInstance instance = loadBalancerClient.choose("provider-service");
        String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/hello";
        return restTemplate.getForObject(url, String.class);
    }
}

Choosing Apollo therefore adds the overhead of an extra discovery component.

Data Model Comparison

Nacos Three‑Layer Model

Namespace : Represents environment isolation (dev, test, prod). Clients specify the namespace to access a particular environment.

Group : Logical grouping such as DEFAULT_GROUP or DATABASE_GROUP.

DataId : The actual configuration file, typically named ${serviceName}.properties.

# Nacos configuration example
spring.cloud.nacos.config.namespace=dev
spring.cloud.nacos.config.group=DEFAULT_GROUP
spring.cloud.nacos.config.dataId=order-service.properties

The model is clear and similar to Kubernetes namespaces, but managing many environments may require separate Nacos clusters or permission isolation.

Apollo Four‑Layer Model

Environment : DEV, FAT, UAT, PRO.

AppId : Unique application identifier.

Cluster : Data‑center or logical grouping.

Namespace : Represents configuration files, with private and public scopes.

# Apollo configuration example
app.id=order-service
apollo.meta=http://config-server:8080
apollo.bootstrap.namespaces=application,TEST1.public
apollo.cluster=default

Apollo’s model is richer, naturally supporting multi‑environment and multi‑cluster setups, but the added layers increase the learning curve.

Architecture Comparison

Nacos Architecture
Nacos Architecture

Nacos nodes are peers; data consistency is ensured via a shared MySQL store. Clients can configure multiple server addresses or use a load balancer.

Apollo Architecture
Apollo Architecture

Apollo’s architecture consists of distinct components (ConfigService, AdminService, Portal, MetaServer). This separation allows independent scaling of each component but raises deployment complexity.

Performance & Scalability

Nacos Server on an 8‑core, 16 GB machine sustains 5,000+ concurrent long‑polling clients.

Apollo’s ConfigService is stateless and scales well, but the underlying database can become a bottleneck under massive client loads because every configuration fetch hits the DB (caching mitigates this).

Nacos also relies on a database but adds a server‑side cache to reduce DB queries.

Both ensure configuration publishing atomicity via database transactions.

Operations Cost & Community Ecosystem

Deployment & Ops : Nacos is simpler—single‑command standalone mode or straightforward cluster setup. Apollo requires at least three services (ConfigService, AdminService, Portal) and two databases (ConfigDB, PortalDB).

Monitoring : Nacos provides a built‑in lightweight monitoring UI; Apollo’s monitoring must be integrated into existing enterprise monitoring systems.

Community : Nacos, backed by Alibaba Cloud, has a very active community (27k+ GitHub stars) and tight integration with Spring Cloud Alibaba, Dubbo, etc. Apollo, backed by Ctrip, also has a mature community (≈28k stars) but releases are less frequent.

How to Choose?

Prefer Nacos When

Starting a new project that uses Spring Cloud Alibaba—configuration and discovery are integrated out‑of‑the‑box.

Team size is small and operational resources are limited.

Service discovery is needed, allowing you to drop a separate discovery system.

Configuration change latency must be sub‑second.

Prefer Apollo When

Operating in a large enterprise with complex configuration governance (multiple environments, clusters, strict permission control, gray releases).

Need deep integration with existing CMDB or monitoring systems via Apollo’s rich APIs and event mechanisms.

Configuration security and auditability are paramount (e.g., finance, government).

Already have a mature service‑discovery solution and only need a dedicated configuration center.

Hybrid Approach

Some teams adopt a mixed architecture: use Nacos for service discovery and Apollo for configuration management, leveraging the strengths of both.

Dynamic Refresh Implementation

Nacos Dynamic Refresh

@RestController
@RefreshScope
public class NacosConfigController {
    @Value("${my.config:default}")
    private String myConfig;

    @GetMapping("/nacos/config")
    public String getConfig() {
        return "Current config: " + myConfig;
    }
}

Modifying the configuration in the Nacos console instantly reflects in the endpoint without restarting; @RefreshScope is the key.

Apollo Dynamic Refresh

@RestController
@RefreshScope
public class ApolloConfigController {
    @Value("${my.config:default}")
    private String myConfig;

    @GetMapping("/apollo/config")
    public String getConfig() {
        return "Current config: " + myConfig;
    }
}

Add @EnableApolloConfig on the application’s main class.

The default refresh interval is 60 seconds; to force immediate refresh you can call ConfigService ’s API or integrate a message bus.

Conclusion

Neither Nacos nor Apollo is universally “better”; each excels in different contexts. Choose Nacos for simplicity, integrated service discovery, and rapid configuration changes. Choose Apollo for enterprise‑grade governance, fine‑grained permissions, and sophisticated gray‑release capabilities. Understanding the trade‑offs helps avoid future pitfalls when the system grows.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

MicroservicesService DiscoveryNacosSpring Cloud AlibabaApolloConfiguration CenterDynamic Refresh
Su San Talks Tech
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.