Using Jule’s hierarchical config loader safely in production
Learn how Jule merges base and environment YAML files, when to enable watch mode, and how to verify a correct load without downtime.
22 Sept 2025, 06:42 UTC

Quick answer
Enable the watch flag only when you need live reload; otherwise restart the process after editing configuration files to guarantee that the latest values are applied and to avoid stale settings.
How the loader works
Hierarchical merge at startup
Jule reads a base YAML file (for example application.yml) and then merges one or more environment‑specific files such as application-dev.yml. The merge follows a depth‑first, recursive strategy: values from files that appear later in the sequence overwrite those from earlier files, while nested structures are combined element by element. This means that a change to a nested map in an environment file will affect only the keys that exist in that file, leaving unrelated sections untouched.
Example configuration hierarchy:
# application.yml (base)
app:
port: 8080
enabled: true
features:
- cache
- logging
# application-dev.yml (environment)
app:
port: 9090 # overrides base port
db:
host: dev-db.example.com # new nested key
port: 5432 # new nested key
features:
- cache # keeps base value
- monitoring # adds new value
After the merge, the effective configuration contains app.port = 9090, app.db.host = dev-db.example.com, and app.features = ["cache", "logging", "monitoring"]. The loader resolves the full hierarchy before the application starts, so the runtime sees a single, consistent data structure.
Command to test loading
Run jule --config-test path/to/application.yml. This command loads the base file and all merged environment files, validates that all simple keys (strings, numbers, booleans, lists, maps) are present, and exits with status 0 on success or a non‑zero exit code if a required key is missing or a type mismatch occurs. No special privileges are required beyond read access to the YAML files.
Typical usage in a CI pipeline or a local development session ensures that the configuration can be parsed before the service is started.
When to enable watch mode
Adding the --watch flag starts a background file‑watcher thread that monitors the configuration files for changes. When a file is modified, Jule reloads the merged configuration without requiring a process restart. This is useful during active development or in environments where configuration updates are frequent and downtime must be avoided.
However, watch mode introduces overhead: the watcher thread consumes CPU cycles and memory, and it batches file system events, which can cause a short lag between a file edit and the actual reload. In high‑throughput services, this latency may be unacceptable, and rapid successive edits may result in the configuration being stale for a brief period. Therefore, enable watch mode only in low‑traffic or development contexts, and monitor the log for “Configuration reloaded” messages to verify that updates are applied as expected.
Limits and common mistakes
- Validation is limited to simple keys; complex expressions, function calls, or YAML anchors that evaluate to code are rejected. A mis‑typed value such as
app.port: "8080"(string) is accepted, but an attempt to embed a Python expression will cause a runtime error. - Missing an environment file leads to absent mandatory settings, resulting in a startup failure. Always verify that each required environment file (e.g.,
application-prod.yml) exists before launching the service. - Versions prior to 2.3 used a flat merge strategy, where later files overwrote entire sections rather than merging nested structures. Upgrading to 2.3+ may change the effective configuration, so review the merge behavior after an upgrade.
Verification steps
- Execute
jule --config-test path/to/application.yml. The command should return exit code 0 and print no error messages. If it fails, inspect the reported missing key or type mismatch. - After starting the service, look for log lines such as
Configuration loaded from application.yml, application-dev.yml. These lines confirm that the expected files were read and merged. - Use
jule env dumpto output the fully resolved configuration to stdout or a file. Compare the output against a version‑controlled test fixture that contains the expected values. Any discrepancy indicates a mis‑merge or missing file.
Practical checklist
- Confirm that every environment file required for the target profile is present in the configuration directory.
- Run the
--config-testcommand in the same environment where the service will run (e.g., same user, same working directory). - Enable
--watchonly after verifying that configuration changes are infrequent; otherwise prefer a restart to avoid stale data. - Monitor startup and runtime logs for “Configuration loaded” and “Configuration reloaded” messages to ensure the correct files are being used.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.