# Netflix Archaius 2.x: dynamic configuration for Java services that cannot restart

> Archaius 2.x splits a config API from its backing sources and keeps property reads lock-free so timeout values and feature flags can change without a redeploy. It is a good fit for JVM services that already run Guice and need polling or fine-grained refresh; it is not a drop-in for Archaius 1.x.

**Netflix/archaius** — Library for configuration management API

- Repository: https://github.com/Netflix/archaius
- Stars: 2,498 · Forks: 476
- Language: Java
- License: Apache-2.0
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/netflix-archaius

## The restart problem Archaius 2.x is built around

Most Java services read configuration once at startup. A timeout, a connection pool size or a feature flag is loaded into a static field, and changing it means a redeploy. Archaius exists to remove that step. The README describes the library as a way to access "a mixture of static as well as dynamic configurations as a single configuration unit", and it names dynamic configuration as "one of the core differentiators between Archaius and other configuration libraries". The intended reader is a service owner who wants to adjust a value in production and have running code see it, without a restart and without a service interruption during what the README calls "minor configuration changes, such as timeout values".

The 2.x line is a deliberate break. The README states plainly that it is "Not backwards compatible with 1.x." The rewrite separates the API from the backing store, so commons-configuration and typesafe-configuration live in their own modules rather than being baked into the core, and the bootstrapping process no longer depends on class loading. That last point matters if you have ever debugged a library that discovered its own configuration through static initializers and reflection: the order of class loading becomes part of your configuration semantics, and Archaius 2.x removes that coupling.

## Properties, Configs and the CompositeConfig override chain

Archaius draws a line between two things. Properties are the individual values your code reads. Configurations are objects that group properties and are composed together to form the configuration your application boots from. A com.netflix.archaius.api.config.CompositeConfig stacks several sources into one override structure, so a value can come from a remote snapshot, a local file, system properties or environment variables depending on which layer wins.

Reading goes through com.netflix.archaius.api.Config, which exposes getString(), getInt() and getBoolean() and can also parse into any type with a single-String constructor or a static valueOf(String.class) method. That is a small but useful escape hatch: an enum or a custom value class does not need a hand-written converter. Values also support standard replacement syntax, written as ${other.property.name}, so one property can be defined in terms of another and resolved through the same hierarchy.

The loader side is where the layering gets interesting. Archaius ships a default loader for .properties files and can be extended with custom property specifications such as HOCON. A com.netflix.archaius.api.CascadeStrategy derives multiple contextual overrides for a single configuration resource name, and it can pull replacements from configurations that are already loaded, including system and environment properties. In practice this is how you get a per-region or per-application override without duplicating the whole file.

## How dynamic refresh actually reaches your code

Dynamic support is split into loading and resolution, and the split is worth understanding before you wire anything up.

On the loading side, when you add a DynamicConfig-derived configuration, CompositeConfig registers for change notifications and folds new values into the main configuration. Archaius provides PollingDynamicConfig for sources that are polled to refresh the entire snapshot, and the README points out that you should implement Config directly for fine-grained sources such as ZooKeeper, which update individual properties rather than replacing the whole set. That is a real design fork: whole-snapshot polling is simple but rewrites everything on each tick, while per-property updates need a source that can deliver them.

On the resolution side, the Property API is the fast path. The README notes that Property optimizes caching of the resolved value from the hierarchy and is "much more efficient than calling the Config object for frequently accessed properties". Two access patterns are documented. The common one reads the latest value directly from a Property object. The advanced one registers a com.netflix.archaius.api.PropertyListener and reacts to changes, which is how you would call socket.setReadTimeout(value) when a timeout property moves. The README's own example wires a listener that applies the new value to an open socket. That is the pattern to copy for anything that must take effect immediately rather than on the next read.

## Installing Archaius 2.x and reading a first dynamic property

Archaius is a JVM library distributed through Maven, and the repository is organized as a Gradle multi-module build with archaius2-api, archaius2-core, archaius2-guice, archaius2-persisted2, archaius2-typesafe, archaius2-commons-configuration, archaius2-archaius1-bridge and archaius2-test as top-level modules. The README does not print a dependency coordinate, so take the group and artifact from the module you need rather than guessing; com.netflix.archaius:archaius2-core is the module that carries ProxyFactoryTest, the example the README tells you to read.

The README's entry point for learning the bootstrapping sequence is that test class, not a quickstart. It says to check com.netflix.archaius.ProxyFactoryTest under archaius2-core/test/java/ for an example of bootstrapping a config and accessing dynamic properties. Start there, because the module layout tells you which pieces you actually need to depend on.

Once you have a Config, the property factory is created from it:

```java
DefaultPropertyFactory factory = DefaultPropertyFactory.from(config);
```

Then you declare a typed property with a default, which is the form you keep in a field and read on the hot path:

```java
Property<Integer> timeout = factory.getProperty("server.timeout").asInteger(DEFAULT_TIMEOUT_VALUE);
```

And you read the cached value rather than the config object:

```java
Thread.sleep(timeout.get());
```

To see a change take effect, attach a listener. The README's example takes a property without a default and applies the value on change:

```java
Property<Integer> timeout = factory
    .getProperty("server.timeout")
    .asInteger()
    .addListener(new PropertyListener<Integer>() {
        public void onChange(Integer value) {
            socket.setReadTimeout(value);
        }

        public void onError(Throwable error) {
        }
    });
```

If your source is a remote snapshot rather than a local file, the README shows adding a polling configuration to a CompositeConfig with a fixed interval:

```java
config.addConfig(new PollingDynamicConfig(
            "REMOTE", 
            new URLConfigReader("http://remoteconfigservice/snapshot"), 
            new FixedPollingStrategy(30, TimeUnit.SECONDS)) 
```

The reader is told the configuration refreshes every 30 seconds in that arrangement. What you should expect to see is the value from the remote snapshot winning over lower layers once the first poll completes, and the listener firing on the poll where the value actually differs.

## Where Archaius 2.x will cost you

The 1.x incompatibility is the first real cost, and it is not a deprecation cycle. The README states it as a fact rather than a migration path, and the repository includes an archaius2-archaius1-bridge module, which tells you the project expects some users to need a bridge rather than a clean port. If your codebase calls Archaius 1.x APIs directly across many classes, budget for that work before you start.

The second cost is the polling model. FixedPollingStrategy refreshes the entire configuration snapshot on an interval. For a small snapshot that is fine. For a large one, every poll transfers and re-parses the whole thing, and the refresh interval becomes a trade-off between how fast a change propagates and how much traffic your configuration service absorbs. The README's answer for fine-grained sources is to implement Config directly, which means writing your own change-notification plumbing against a source like ZooKeeper. That is more code than most teams expect when they read the phrase "dynamic configuration".

The third cost is documentation depth. The README gives the core concepts, a handful of snippets and one test class to read. It does not document a rollback procedure, a failure mode for an unreachable remote source, or what happens to already-resolved properties when a poll fails. Those are exactly the questions that come up in production, and the README is silent on them. Treat the test sources as the specification.

Finally, Archaius is the wrong tool when configuration genuinely does not change at runtime. If your values are fixed at deploy time, a properties file plus your framework's own binding is less machinery, fewer moving parts and one less polling loop to operate.

## Archaius 2.x compared with Spring Cloud Config and Consul-backed setups

The obvious alternative for a JVM service is Spring Cloud Config, usually paired with a Spring Boot application. The difference is where the refresh boundary sits. Spring Cloud Config treats the configuration server as a separate service that serves an Environment to the client, and refresh is normally driven by an explicit trigger such as an actuator endpoint or a message bus event, with @RefreshScope beans rebuilt when that happens. Archaius instead embeds the composition inside your process: a CompositeConfig stacks sources, a polling or fine-grained DynamicConfig feeds it, and a Property object caches the resolved value so hot reads stay cheap. Archaius also does not require Spring; the README calls out Guice friendliness and a bootstrapping process that avoids static code execution, and the repository ships an archaius2-guice module for that path.

A second alternative is to read configuration from a key-value store directly, for example Consul or etcd with a watch API, and skip the library. That gives you per-key updates and no snapshot polling, which is the model Archaius itself recommends you implement Config for when the source supports it. What you give up is the override hierarchy, the ${other.property.name} replacement syntax and the typed property factory. If your configuration is flat and your source already pushes changes, the library may be more structure than you need. If you have layered defaults, environment overrides and a handful of hot values, the composition is the part that saves you from writing it yourself.

## Conclusion

Adopt Archaius 2.x if you run a JVM service that must pick up timeout, pool or flag changes without a restart, and you are willing to bootstrap a CompositeConfig and route hot reads through DefaultPropertyFactory. Do not adopt it if you are already on Archaius 1.x and cannot absorb the breaking API change, or if your configuration never changes at runtime and a plain properties file is enough. Before committing, verify three things in your own tree: that the artifact coordinates you intend to use resolve from Maven Central, that your service can host a polling loop at the interval you choose, and that the property names you plan to override actually appear in the cascade you configure.

## FAQ

### What is Netflix Archaius?

It is a Java configuration library for reading static and dynamic configuration as a single unit. The README describes two concepts: properties your code reads, and configurations that group properties into objects used to bootstrap an application. It is best known for dynamic properties that change without a restart.

### What are the alternatives to Netflix Archaius?

The README does not name competing libraries, so no direct substitute can be confirmed from it. What can be said is that Archaius supports custom property specifications such as HOCON and can be extended with your own loaders, and that for fine-grained sources like ZooKeeper the documentation tells you to implement Config directly rather than use the polling base class.

### Is Archaius 2.x compatible with Archaius 1.x?

No. The README lists "Not backwards compatible with 1.x" as the first item under 2.x changes. The repository does include an archaius2-archaius1-bridge module, which suggests a bridge path exists, but the README does not document how to use it.

### How do I read a dynamic property with Archaius?

Create a DefaultPropertyFactory from your Config, declare the property with a type and default, then read the cached value. For values that must take effect immediately, attach a PropertyListener and apply the new value in onChange, as the README does with socket.setReadTimeout.

### How does Archaius refresh a remote configuration?

The README shows adding a PollingDynamicConfig to a CompositeConfig with a URLConfigReader and a FixedPollingStrategy, in its example every 30 seconds. CompositeConfig then registers for change notifications and folds new values into the main configuration. For sources that update individual properties, the README says to implement Config directly.

## Sources

- [Issues](https://github.com/Netflix/archaius/issues)
- [License: Apache-2.0](https://github.com/Netflix/archaius/blob/2.x/LICENSE)
- [Netflix/archaius on GitHub](https://github.com/Netflix/archaius)
- [README](https://github.com/Netflix/archaius/blob/2.x/README.md)
- [Releases](https://github.com/Netflix/archaius/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/netflix-archaius
