dynamic-config
Hot-reloadable, lock-free application configuration for Rust: one attribute declares the type, one builder states its sources.
- crates.io: https://crates.io/crates/dynamic-config
- API documentation: https://docs.rs/dynamic-config
- Source: https://github.com/dynamic-config-rs/dynamic-config
Why
Configuration in a long-running service has three awkward properties at once: it comes from several sources with a precedence order, it is read on nearly every request from many threads, and it should be changeable without a restart.
Doing that by hand means a RwLock<Config> on the read path, a bespoke file
watcher, and a reload that must not take the process down when someone saves a
broken file. This crate is all three.
config | figment | Go's Viper | dynamic-config | |
|---|---|---|---|---|
| Layered sources | ✅ | ✅ | ✅ | ✅ |
| Hot reload | ❌ | ❌ | ✅ | ✅ |
| Lock-free reads | — | — | not thread-safe | ✅ |
| Reload keeps last good config | — | — | ❌ | ✅ |
| Typed struct API | ✅ | ✅ | partial | ✅ |
| Async: await config changes | ❌ | ❌ | callback | ✅ |
The loader is this crate's own: it reads the documents, walks the environment, folds the layers in precedence order and records which one won each key as it wins. How resolution works is that walk in full. Around it sits everything a long-running service needs and a startup-time loader does not: the attribute and its builder, the lock-free snapshot, the watcher, and a reload that cannot take the process down. Comparisons is the row-by-row version of the table above, and CREDITS.md is what this engine owes to each of them.
The shape of the crate
| Two mandatory dependencies | serde and arc-swap. The default engine's crate makes a third in a default build and --no-default-features takes it away again; every format, client, crypto stack and runtime is behind a feature or in a companion crate |
#![forbid(unsafe_code)] | in every crate here, checked by CI rather than trusted |
| MSRV 1.88 | one number for core, every feature, the CLI and the embedded cell — verified against the real toolchain |
| No global singleton | each configuration type owns its storage; there is no Config::get() returning something a library set |
no_std | a separate crate for microcontrollers: no filesystem, no allocator, no runtime |
Contributing and security
docs/CONTRIBUTOR-ONBOARDING.md is a tour of every crate and module — what each does and where you would change it. CONTRIBUTING.md has what a change should carry and what is load-bearing enough to argue about. SECURITY.md states the properties this crate tries to keep — and the ones it explicitly does not — along with how to report a vulnerability privately.
just check runs what CI runs; just containers adds the suites that need a
Docker daemon.
License
MIT