Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Stability Tiers

Every crate in this workspace is Beta, and one is not a tier at all.

CrateTier
dynamic-configBeta
dynamic-config-macrosBeta
dynamic-config-etcdBeta
dynamic-config-consulBeta
dynamic-config-natsBeta
dynamic-config-redisBeta
dynamic-config-vaultBeta
dynamic-config-s3Beta
dynamic-config-firestoreBeta
dynamic-config-gitBeta
dynamic-config-embeddedBeta
dynamic-config-serverBeta
dynamic-config-cliBeta
dynamic-config-py, dynamic-config-py-remoteBeta
dynamic-config-node, dynamic-config-node-remoteBeta
dynamic-config-py-webBeta, two adapters Experimental — see below
dynamic-config-web-core, dynamic-config-axum, dynamic-config-actixBeta
dynamic-config-store-coreno API — see below

The axum and Actix crates carry one promise and a small surface. A Sections list, a Snapshot, a layer and an extractor — no lifecycle, no routes, nothing that loads or watches. Their floor is the organisation's one 1.88 (loco alone sits at 1.94, loco's own), checked against the real toolchain; raising it is a breaking change.

dynamic-config-py-web is one distribution with two tiers inside it. Its seven adapters for FastAPI, Litestar, Flask, Quart and Django — the Django REST Framework and django-ninja layers included — are Beta: each uses a first-class, documented seam of a framework with a long release history, and all of them pass the same twelve-case behavioural suite.

The Robyn and django-bolt adapters are Experimental: both frameworks are young, django-bolt classifies itself Alpha and requires Python 3.12, and what is most likely to move under them is exactly the part an adapter needs — the process model and the request lifecycle. Concretely, those two may change surface in a minor release of that package, and its [all] extra does not install them.

The store crates were Experimental until 0.6.1, and what moved them is evidence rather than time. Each is tested against a real server in a container; each watch loop's failure branches are enumerated in a table in that crate's own documentation; three of them are unplugged mid-watch by just chaos — toxiproxy in front of a store that never restarts — and asserted to report the outage without losing the document they were serving. The surfaces stopped moving two releases ago. That is what the old tier said the path out was, and this is it.

What Beta promises

The core crate and the macro are Beta. The API is settled enough to build on, but pre-1.0 it may still break — and when it does, the break lands in a minor version bump (0.x → 0.(x+1)), is called out in the changelog, and comes with what to change on your side. A patch release never breaks. MSRV is treated as a breaking change here too, so a toolchain bump follows the same rule.

What the promise covers is what rustdoc renders. A #[doc(hidden)] item is pub because something has to reach it across a crate boundary — the code the attribute generates, or the workspace's own fuzz targets — and it may be renamed or removed in a patch release. __private and __fuzz are the two, and neither appears in this book for the same reason it does not appear in the API documentation.

What happens between here and 1.0

Only security fixes and hotfixes. The surface is what it is going to be for 0.x: no new sources, no new stores, no new methods on the settled types. What still lands is a defect that produces a wrong answer, a security advisory, and documentation — and each of those goes out as a patch.

That is a change of intent rather than of policy. From outside the two look alike — a project that publishes weekly because it is growing and one that publishes rarely because it is finished are both quiet — so it is stated here rather than left to be inferred.

What it means for a program that depends on this. Pin the minor version and take patches automatically; a patch will not break you, and the release that could is the 1.0 that is being worked towards. An API that would be nicer is a 1.0 candidate — written down in the roadmap with its argument — rather than something to slip into a 0.x.

dynamic-config-store-core promises nothing

It is published because a crate that a published crate depends on has to be — cargo resolves a path dependency from the registry when it packages. It holds what the store crates share: the credential cache, URL redaction, the watch panic net. Nothing outside this workspace should depend on it, and it carries no compatibility promise at all, not even Experimental's.

The figment feature is a coupling, on purpose

With the figment feature on, Source::provider and the pub use figment re-export make figment's own API part of this crate's public surface — so a figment major release forces either a major release here or a compatibility shim, and 1.0 of this crate will not extend its stability promise across that boundary. That is the feature's price and its point: it exists precisely so the long tail of sources this crate will never ship stays reachable without forking. With the feature off — the default — figment is not in the dependency graph at all, and a figment major bump is not a breaking change here.