figment

A hierarchical configuration library for Rust that merges TOML, JSON, YAML, and env vars

Library
Cargo
v0.10.19
908stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
36/100Needs Attention
Development Activity0
Maintenance0
Community44
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
78/100Good
Architecture82
Code Quality76
Innovation74
Learning Curve78

Figment is a semi-hierarchical configuration library for Rust, created by the author of the Rocket web framework (which uses Figment as its own config system). It lets applications merge configuration from multiple sources — TOML files, JSON files, YAML files, environment variables, or custom providers — into a single typed struct via serde::Deserialize, with later-merged sources overriding earlier ones field-by-field rather than replacing whole sections.

The design centers on a small Provider trait so any data source (built-in or third-party, such as the community figment_file_provider_adapter crate) can participate in the same merge/join pipeline. Figment ships built-in providers for TOML, JSON, YAML, and prefixed/raw environment variables, each gated behind its own Cargo feature so consumers only compile in the formats they actually use.

What You Get

  • A Figment builder that merges (field-level override) or joins (fill-in-the-gaps) multiple config Providers in sequence
  • Built-in providers for TOML, JSON, and YAML files, each behind its own opt-in Cargo feature
  • Environment variable providers (Env::prefixed, Env::raw) for injecting env vars into the same merged config
  • A Provider trait that lets third-party crates (e.g. figment_file_provider_adapter) plug custom sources into the same pipeline
  • Typed extraction via serde::Deserialize, so the final merged configuration is a normal, strongly-typed Rust struct

Common Use Cases

  • Layering a base TOML config file with environment-variable overrides for different deployment environments (dev/staging/prod)
  • Building a web framework or CLI tool’s configuration system, as Rocket itself does internally with Figment
  • Merging a project manifest file (like Cargo.toml) with supplemental JSON config into one typed struct
  • Allowing library consumers to override individual config fields via env vars without needing to specify a whole config block

Under The Hood

Architecture The crate centers on a small Provider trait (in src/) that any config source implements by returning a Dict/Value tree; Figment::merge() and Figment::join() combine multiple providers’ trees with different override semantics (merge replaces at the field level, join only fills in missing keys), and Figment::extract() deserializes the combined tree into a caller-supplied serde::Deserialize type. Built-in TOML/JSON/YAML/Env providers (each behind a feature flag) are just implementations of this same trait, which is also why third-party crates can add new source types without needing changes to Figment itself. Tech Stack Rust, 2018 edition. Depends on serde for the deserialization target, uncased for case-insensitive key matching, and optional format-specific dependencies (toml_edit, serde_json, serde_yaml) gated behind the toml/json/yaml features. A build.rs uses version_check to detect nightly Rust for conditional compilation. Code Quality 21 source files and 8 dedicated test files, with a test feature (pulling in tempfile and parking_lot) specifically for exercising file-based providers. The repository has had no commits since September 2024 per its GitHub activity, meaning it is currently in a low-activity, maintenance-only state — worth noting for anyone evaluating it for a project with active feature needs, though the core is stable and used in production by Rocket. API Design The merge/join/extract builder chain reads close to natural language (Figment::new().merge(Toml::file(...)).merge(Env::prefixed(...)).extract()), and gating each file format behind its own feature flag keeps the default dependency footprint minimal. The tradeoff of the generic Provider-tree design is that error messages point at the merged Value tree rather than a specific source file/line in some cases, which can require a bit more debugging than a single-format parser would.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search