16 KiB
Nacos Plugin Spec
Purpose
Nacos uses plugins and SPI extensions to keep cross-cutting infrastructure and replaceable domain capabilities outside the fixed core. A plugin may provide authentication, resource visibility, data source dialects, encryption, tracing, flow control, environment adaptation, AI pipeline behavior, AI storage behavior, AI resource import behavior, or Java client-side request adaptation.
The plugin mechanism must let Nacos keep a stable core model while allowing deployments to choose an implementation that matches their identity system, database, observability stack, or extension scenario.
Plugin Identity
Every plugin is identified by:
pluginType: the extension category, such asauthorvisibility.pluginName: the implementation name inside that category, such asnacos.pluginId: the runtime identifier in the form{pluginType}:{pluginName}.
The pluginId is the value used by the admin plugin API, cluster state
synchronization, persisted plugin state, and user-facing diagnostics.
Plugin Types
The current plugin type registry is defined by PluginType.
| Type | Purpose | Contract |
|---|---|---|
auth |
Authentication and authorization implementation. | Auth Plugin Spec |
visibility |
Resource visibility and query visibility advisory. | Visibility Plugin Spec |
datasource-dialect |
Database dialect and persistence adaptation. | Data Source Dialect Plugin Spec |
config-change |
Configuration change extension. | Config Change Plugin Spec |
encryption |
Encryption and decryption extension. | Config Encryption Plugin Spec |
trace |
Trace and observability extension. | Trace Plugin Spec |
environment |
Environment adaptation extension. | Environment Plugin Spec |
control |
Traffic and control extension. | Control Plugin Spec |
ai-pipeline |
AI registry pipeline extension. | AI Publish Pipeline Plugin Spec |
ai-storage |
AI registry storage extension. | AI Storage Plugin Spec |
ai-resource-import |
AI registry external import extension. | AI Resource Import Plugin Spec |
Domain-specific plugin contracts are defined by their own specs. This document defines the common runtime contract shared by all plugin categories.
Addressing extension is documented with plugin
specs for continuity with the public plugin documentation, but current server
code handles it through MemberLookup and does not register it in PluginType.
Runtime Location
Nacos has two plugin-like extension surfaces:
| Runtime | Loading model | State owner | Examples |
|---|---|---|---|
| Server plugin | Domain SPI plus PluginProvider, listed and managed by server plugin APIs where supported. |
Nacos server process and, for managed plugins, server plugin state. | auth, visibility, datasource-dialect, control, trace. |
| Java client extension | Java SPI or SDK API loaded inside the client process. | Client classpath, client properties, and SDK instance lifecycle. | ServerListProvider, ClientAuthService, IConfigFilter, client-side config encryption. |
Client extensions are not managed by /v3/admin/core/plugin/* and do not have a
server-side PluginStateCheckerHolder decision unless their corresponding
server plugin also participates in request handling. They must still follow
Nacos resource identity, authorization, and payload semantics because they shape
requests sent by the SDK.
Execution Modes
Plugin categories do not all execute in the same shape. A plugin type must define its execution mode explicitly.
| Mode | Meaning | Examples |
|---|---|---|
| Exclusive selection | One implementation is selected for the process or request scope. Other loaded implementations remain inactive for that decision. | auth, datasource-dialect |
| Configured single service | Multiple implementations may be loaded, while a domain chooses one service by configuration or request context. | visibility, ai-resource-import |
| Ordered chain | Multiple matching plugins are invoked in a stable order. Each node may contribute a result, and the domain defines whether failure stops the chain. | ai-pipeline, config-change |
| Subscriber or broadcast | Multiple subscribers observe the same event or trace point without owning the primary decision. | trace, event-style extensions |
For chained plugins, the domain SPI must define:
- How candidate plugins are selected for a resource or pointcut.
- Which field controls ordering, such as
getPreferOrder()orgetOrder(). - Whether execution is serial or parallel.
- Whether a failed plugin stops the chain or only records a failed result.
- How partial results are persisted and exposed.
The core plugin manager records loaded and enabled plugins; it does not by itself define the execution mode. Domain managers are responsible for applying the mode consistently.
SPI Layers
Nacos plugins have two related SPI layers:
- Domain SPI, such as
AuthPluginServiceorVisibilityService, defines the behavior required by the owning domain. - Core plugin SPI,
PluginProvider, exposes plugin instances to the core plugin manager for listing, status management, configuration, and observability.
A plugin that needs dynamic configuration implements PluginConfigSpec. A
plugin category that supports enable or disable checks must use
PluginStateCheckerHolder rather than keeping an independent status source.
Loading And Lifecycle
Plugin implementations are discovered with the Nacos SPI loader. Deployments may provide plugins from the classpath or from the server plugin directory. The plugin implementation must be loadable without changing Nacos server code.
The core PluginManager discovers PluginProvider implementations after the
server application is ready. Domain managers may also load their domain services
through SPI, but availability decisions must still respect the plugin state held
by the core plugin manager.
Plugin startup must be deterministic:
- A plugin type and name pair must map to one runtime plugin instance.
- Duplicate plugin names in the same type are invalid for stable operation.
- Plugin implementations must not change the meaning of shared Nacos resource identifiers, response envelopes, or error conventions.
State And Configuration
Plugin state has two levels:
- Loaded: the implementation exists in the runtime.
- Enabled: the implementation may participate in request handling.
Most plugin types are enabled by default after loading. Exclusive plugin types select one default implementation:
| Type | Default selection rule |
|---|---|
auth |
The implementation named by nacos.core.auth.system.type, default nacos. |
datasource-dialect |
The configured SQL platform, default derby. |
Critical plugins cannot be disabled while the server depends on them. The current critical set includes built-in data source dialects and the default AI storage plugin required by the server.
Plugins with PluginConfigSpec expose config definitions, current config, and
config application behavior. Cluster-wide status or config changes must be
synchronized through the plugin state operation path unless the request is
explicitly local only.
Configuration Definition
Plugin config items are described by ConfigItemDefinition. The key field is
the canonical item key inside the plugin implementation and does not include the
nacos.plugin.{pluginType}.{pluginName}. prefix. Static configuration should
prefer this normalized full key:
nacos.plugin.{pluginType}.{pluginName}.{itemKey}
Config definitions may declare the following metadata:
| Field | Meaning |
|---|---|
aliases |
Historical static config keys for compatibility and migration hints. |
sensitive |
Whether the value is sensitive. Query APIs must mask it before returning. |
effectMode |
Effect mode. RUNTIME can take effect at runtime, and RESTART requires restart. |
aliases are used when reading compatible static configuration and may also be
accepted as migration-compatible API input. After normalization, aliases must
not be written into runtime persistence files or local-only memory maps. If an
input contains multiple aliases for the same item, the first alias declared in
the definition takes effect and the server logs the ignored aliases.
Config Sources And Value Metadata
Effective plugin config values are computed by a unified resolution flow. Source priority is:
LOCAL_ONLY > RUNTIME_PERSISTED > STATIC > DEFAULT
| Source | Meaning |
|---|---|
DEFAULT |
Value from ConfigItemDefinition.defaultValue. |
STATIC |
Value from static configuration, such as application.properties, environment variables, JVM parameters, or Spring parameters. |
RUNTIME_PERSISTED |
Cluster-wide runtime override. It may currently be persisted as the final content in plugin-configs.json. |
LOCAL_ONLY |
Current-node override for diagnosis or emergency handling, not synchronized to the cluster. |
Plugin detail responses may add a configValueMetas map keyed by canonical item
key. Each PluginConfigValueMeta describes the current source and overridden
state of one config item. overridden ignores DEFAULT and should be true
only when the same key has multiple non-default sources.
Runtime persisted config and local-only config store only values by
pluginId + itemKey. They do not store normalized full keys, alias keys,
source, or version information.
Every internal source resolver must expose its canonical item-key map through
getConfig(PluginInfo). Reading is independent from update capability:
DEFAULT reads definition defaults, STATIC reads normalized and alias keys
from the environment, and the two runtime sources read their internal maps.
isUpdatable is checked only when replacing a source map. An update replaces
the complete map; an empty map clears all overrides for that plugin and source.
The source contract does not require separate remove or restore operations.
Config Update Compatibility
Plugin detail APIs must remain additively compatible: existing config and
configDefinitions fields remain available. config may represent the current
effective config, and the added configValueMetas map carries source and
overridden metadata by canonical item key.
PUT /v3/admin/core/plugin/config and the matching Console API keep the current
full override map update semantics. localOnly=true updates only the current
node local-only override; otherwise the request updates the cluster-wide runtime
persisted override. Key normalization and effectMode checks are server-side
logic and are not exposed as new API parameters. Fields marked
effectMode=RESTART must not be applied immediately by runtime updates. The
server compares the previous and submitted full map for the target source, so
adding, changing, or removing a RESTART item is rejected. Omitting a key from
the submitted map therefore removes its override only when that item is
runtime-effective.
Canonical item keys, normalized full keys, and compatible alias keys are
normalized to item keys before validation and storage. An undefined key or an
alias that ambiguously matches multiple config items must produce a parameter
validation error.
For an item declared sensitive=true, a submitted value containing the
standard ****** marker is treated as a masked display value. If the target
source already contains that item, the server preserves the original value
from that same source. If the target source does not contain the item, the
input is ignored and no override is created. This rule also covers values such
as a******z and ab******yz; it must not copy an effective value from another
source such as STATIC into a runtime override. The server logs a warning with
only pluginId, item key, and target source, and must not log the value.
Initialization And Runtime Apply
Startup and runtime updates use the same source resolver and effective config calculation:
- Startup loads all
plugin-configs.jsonentries into the runtime persisted source before applying any plugin config. - Every loaded configurable plugin is then resolved and applied, including
plugins without a persisted override. Startup may apply both
RUNTIMEandRESTARTfields because the plugin is being initialized. - A runtime request replaces one complete
RUNTIME_PERSISTEDorLOCAL_ONLYsource map. The server resolves all sources again and invokes the plugin for each accepted request, including a same-map request used as a manual retry.
Updates for the same plugin are serialized. A runtime persisted update first
persists the normalized complete source map, replaces the resolver source,
resolves and validates the effective config, and then applies it to the plugin.
If persistence fails, the resolver source and plugin are not changed and no
rollback is attempted. If apply fails after the source update, the accepted
source map remains persisted and resolved; the server does not issue an
automatic rollback or compensation update. The API returns an explicit server
error that the config was updated but apply failed, and the server logs the
plugin ID and source without config values. Repeating the same complete map is
a supported manual apply retry. A LOCAL_ONLY update follows the same
replace-resolve-apply behavior without persistence or synchronization; its new
local source map also remains when apply fails.
Admin API
The core plugin admin API is:
| Method | Path | Purpose |
|---|---|---|
GET |
/v3/admin/core/plugin/list |
List loaded plugins, optionally filtered by type. |
GET |
/v3/admin/core/plugin/detail |
Read one plugin detail with effective config and optional value metadata. |
PUT |
/v3/admin/core/plugin/status |
Enable or disable a plugin. |
PUT |
/v3/admin/core/plugin/config |
Update plugin configuration. |
These endpoints are Admin APIs and require console-scoped authorization as defined by the HTTP Authorization Spec. Plugin management must use the standard v3 response and error model.
Design Requirements
Plugin implementations must follow these rules:
- Use existing Nacos resource identifiers and domain models instead of inventing an incompatible model for the same resource.
- Preserve v3 HTTP API response, error, and authorization conventions for any plugin-provided HTTP APIs.
- Expose only plugin-owned configuration through
PluginConfigSpec. - Keep cluster-wide state changes synchronized unless the caller explicitly requests a local-only operation for diagnosis or emergency handling.
- Document security-sensitive defaults and deployment requirements in the plugin implementation spec.
The plugin mechanism is an extension boundary, not a license to bypass Nacos resource, API, or security rules.