Library / SDK
rust-cli/config-rs avatar
rust-cli/config-rs

config-rs: A Layered Configuration Crate for Rust Applications

⚙️ Layered configuration system for Rust applications (with strong support for 12-factor applications).

3,215 stars265 forksRustApache-2.0

At a glance

What is it?
config-rs builds a single configuration view from defaults, files and environment variables, with a JSONPath-like lookup syntax. It reads configuration but never writes it back, and its file-format support sits behind feature flags.
Who is it for?
config-rs suits Rust services that need defaults, file values and environment variables merged in a defined order, and teams willing to keep writes out of the library. It is the wrong tool if you need to persist changed settings back to a file, since the README states this library cannot write changed configuration values back.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem config-rs solves for Rust services

A service needs a default port, a value from a checked-in TOML file, and an override from an environment variable when it runs in a container. Doing that by hand means writing the merge logic yourself, and the merge order is exactly where bugs live. config-rs exists to make that layering explicit. The README lists what a caller can do: set defaults, set explicit values to programmatically override, read from JSON, TOML, YAML, INI, RON, JSON5 and CORN files, and read from the environment. The stated audience is Rust applications, with the README calling out strong support for 12-factor applications, where configuration lives in the environment rather than in the repository. The crate is loosely typed: values may be read in any supported type as long as a reasonable conversion exists. Nested fields are reached with a formatted path using a subset of JSONPath, currently the child operator such as redis.port and the subscript operator such as databases[0].name. That path syntax is the part most users touch first, and it is also the part with the narrowest documented surface. The scope is deliberately narrow: this is a read-side configuration resolver, not a settings framework with persistence, schema validation or a management UI.

How layering and path lookup actually work

The model is a builder that accumulates sources and then resolves them into one configuration object. Each source you add contributes values, and later sources take precedence over earlier ones, which is what makes defaults, files and environment variables composable. The README does not spell out the full precedence table in the text reproduced here, so the repository's examples/priority directory is the place to confirm the exact order for your version. Lookup is string-based: you pass a path such as redis.port or databases[0].name and ask for a type. The README describes the path support as a subset of JSONPath, with the child operator and the subscript operator listed as the current extent. Anything beyond that, such as wildcards or filters, is not claimed. Because reads are loosely typed, the same underlying value can be requested as a string or a number, and conversion happens at read time. That flexibility is convenient, and it also means a typo in a path surfaces as a missing value at runtime rather than as a compile error. There is no schema file in the repository layout; validation is whatever your code does after the read. The repository also ships examples/watch.rs and examples/async_source.rs, which suggests a source can be watched or resolved asynchronously, though the README text here does not describe those APIs in detail.

Installing config-rs and reading a first value

The crate is published on crates.io as config, and the documentation lives at docs.rs/config. Add it with the file formats you actually use, because JSON, TOML, YAML, INI, RON, JSON5 and CORN each sit behind their own feature flag. The README lists ini, json, yaml, toml, ron, json5 and corn as the flags, so the dependency line names only the ones you need. The repository ships examples/settings.toml alongside examples/simple.rs and examples/static_env.rs, and those files are the reference for the builder calls rather than any snippet invented here. A first use is to point a file source at the settings example, build the configuration, and read a nested key by path; the README's documented path form is the child operator, so a key like redis.port is the shape you query. If the path is wrong, or the file format feature is not enabled, the lookup returns an error rather than a default, which is the expected failure shape. For environment-driven deployment, the crate reads from the environment as well, and examples/static_env.rs shows that pattern. The examples directory also contains watch.rs, async_source.rs, modal/, priority/ and two custom format examples, so the fastest way to learn the API surface is to read those files rather than guess at builder methods.

What config-rs will not do: writing configuration back

The README states plainly that this library cannot be used to write changed configuration values back to the configuration file or files. That is a hard boundary, not a missing feature you can enable. Any application that lets users change a setting at runtime and expects it persisted has to implement serialization and file writing itself, and has to decide how that write interacts with the layering the crate performs on read. A second limitation is format coverage through feature flags. If you enable only toml and ship a YAML file, the read fails. There is no fallback that sniffs the format. The README does describe an extensibility point, a Format trait, for custom or proprietary formats, with a custom_file_format example in the repository. That trait is the escape hatch for formats outside the built-in list, and implementing it is on you. Finally, the path language is documented as a subset of JSONPath. If your configuration needs queries beyond child and subscript access, the crate does not claim to support them. A related practical consequence is that errors are value-shaped: a missing key and a failed conversion both come back from the same lookup call, so distinguishing a typo from a bad file value requires inspecting the error rather than relying on the type system.

config-rs compared with figment

figment is the comparison most Rust developers reach for, and the difference is in how the provider model is exposed. config-rs presents a builder of sources and a string-path lookup with a JSONPath subset. figment is built around providers that can be composed and profiled, and it is designed so that values can be extracted into typed structs through serde. If your application already models configuration as a struct and you want deserialization to drive the shape, figment's provider-and-profile approach maps onto that more directly. If you want to pull individual values by path at the point of use, config-rs is the more direct fit. Neither is strictly better; they push you toward different code organization. The README for config-rs does not contain a comparison section, so the choice should be made by reading both crates' documentation and the examples each ships. One practical difference visible in this repository is the breadth of built-in file formats behind flags, including the less common RON, JSON5 and CORN, which matters if your config files are already in one of those. Another is that config-rs keeps the resolved view as a single object you query repeatedly, whereas a struct-deserialization approach produces one typed value at startup and then stops consulting the configuration layer.

Maintenance, MSRV and licence terms

The repository is not archived, and the last push was on 2026-09-21. The workspace Cargo.toml sets edition 2024 and a rust-version of 1.88.0, which is the MSRV. If your toolchain is older than that, the crate will not build, and that is a concrete upgrade cost to check before adding the dependency. The workspace also carries a long list of clippy lints set to warn, and the repository root includes deny.toml, committed.toml and a pre-commit configuration, which indicates the project enforces its own conventions on contributions. On licensing, the README says the crate is licensed under either Apache License 2.0 or the MIT license, at your option, and both LICENSE-APACHE and LICENSE-MIT are present at the repository root. The Cargo.toml declares the same dual licence as MIT OR Apache-2.0. Dual licensing of this kind is common in the Rust ecosystem, but whether it fits your organization's policy is a question for your legal reviewers, not something this article can settle. The repository also includes a CHANGELOG.md, so upgrade impact between versions is documented there rather than only in release announcements.

Who should adopt config-rs and what to check first

Adopt it if your application reads configuration from a mix of defaults, files and environment variables and needs a defined merge order, and if you are comfortable with string paths and runtime errors for missing keys. It fits services deployed as containers where environment overrides are the normal path. Do not adopt it if you need to write changed values back to a file, because the README rules that out, or if you need query syntax beyond child and subscript path access. Before committing, verify three things: that your toolchain meets the 1.88.0 MSRV, that the feature flags for your file formats are enabled in your Cargo.toml, and that the layering order matches your expectations by reading the examples/priority directory in the repository, since the README text does not enumerate the full precedence rules. If your configuration is already expressed as a Rust struct and you want compile-time shape guarantees, the struct-deserialization model of figment will likely fit better than path lookups, and that is a decision worth making before writing the first read call rather than after.

Editorial conclusion

config-rs suits Rust services that need defaults, file values and environment variables merged in a defined order, and teams willing to keep writes out of the library. It is the wrong tool if you need to persist changed settings back to a file, since the README states this library cannot write changed configuration values back. Before adopting, check the MSRV of 1.88.0 against your toolchain, confirm the feature flags you need are enabled, and read the priority and modal examples in the repository to see how layering behaves.

Frequently asked questions

What is config-rs?

config-rs is a layered configuration system for Rust applications, published on crates.io as config, with strong support for 12-factor applications. It lets you set defaults, set explicit override values, and read from JSON, TOML, YAML, INI, RON, JSON5 and CORN files as well as from the environment.

How do I install config-rs in a Rust project?

Add the config crate to your Cargo.toml dependencies and enable the feature flags for the file formats you use, such as toml or json. The README lists ini, json, yaml, toml, ron, json5 and corn as the available format flags.

Does config-rs support writing configuration values back to a file?

No. The README states that the library cannot be used to write changed configuration values back to the configuration file or files. Persisting changes is something your application has to implement itself.

What is the minimum supported Rust version for config-rs?

The workspace Cargo.toml sets rust-version to 1.88.0, which is the MSRV, and the edition is 2024. A toolchain older than that will not build the crate.

How does config-rs compare with figment?

config-rs exposes a builder of sources plus string-path lookup using a subset of JSONPath, while figment is organized around composable providers, profiles and typed extraction through serde. The config-rs README does not include a comparison, so the choice depends on whether you prefer path lookups or struct deserialization.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. Project website
  4. README
  5. rust-cli/config-rs on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rust-cli-config-rs.svg)](https://hysenlabs.com/projects/rust-cli-config-rs)