npx skills add ...
npx skills add cloudflare/workerd --skill add-autogate
npx skills add cloudflare/workerd --skill add-autogate
Step-by-step guide for adding a new autogate to workerd for gradual rollout of risky changes, including enum registration, string mapping, usage pattern, and testing.
Autogates enable gradual rollout of risky code changes independent of binary releases. Unlike compatibility flags (which are permanent, date-based behavioral changes), autogates are temporary gates that can be toggled on/off via internal tooling during rollout, then removed once the change is stable.
| Use an autogate when... | Use a compat flag when... |
|---|---|
| Rolling out a risky internal change gradually | Changing user-visible behavior permanently |
| You need a kill switch during rollout | The change is tied to a compatibility date |
| The gate will be removed once stable | Users need to opt in or out explicitly |
Autogates and compat flags are separate mechanisms — an autogate does not become a compat flag.
Edit src/workerd/util/autogate.h. Add a new entry to the AutogateKey enum before NumOfKeys:
Naming convention: SCREAMING_SNAKE_CASE for the enum value.
Edit src/workerd/util/autogate.c++. Add a case to the KJ_STRINGIFY switch before the NumOfKeys case:
Naming convention: kebab-case for the string name. This string is what appears in runtime configuration (prefixed with workerd-autogate-). The enum name and string name should match to avoid confusion.
Use Autogate::isEnabled() to conditionally execute the new code path:
Three ways to test autogated code:
A. The @all-autogates test variant (automatic):
Every wd_test() and kj_test() generates a @all-autogates variant that enables all gates. If your feature is tested by existing tests, they'll automatically run with the gate enabled:
B. Targeted C++ test setup:
In a C++ test file, enable specific gates:
C. Environment variable:
Set WORKERD_ALL_AUTOGATES=1 to enable all gates when no explicit config is provided.
Once the human user explicitly confirms that the feature is stable and fully rolled out:
AutogateKey enum value from autogate.hcase from KJ_STRINGIFY in autogate.c++Autogate::isEnabled() checks, keeping only the new code pathAutogateKey in autogate.h (before NumOfKeys)KJ_STRINGIFY in autogate.c++Autogate::isEnabled()@all-autogates test variant passes| File | What to do |
|---|---|
src/workerd/util/autogate.h | Add enum value with comment |
src/workerd/util/autogate.c++ | Add case to KJ_STRINGIFY |
| Your feature file(s) | Guard code with Autogate::isEnabled() |
#include <workerd/util/autogate.h>
// At the point where behavior should change:
if (util::Autogate::isEnabled(util::AutogateKey::MY_NEW_FEATURE)) {
// New code path
} else {
// Old code path (keep until gate is removed)
}just stream-test //src/workerd/api/tests:my-test@all-autogates#include <workerd/util/autogate.h>
// In test setup:
util::Autogate::initAutogateNamesForTest({"my-new-feature"_kj});
// In test teardown:
util::Autogate::deinitAutogate();just build
just stream-test //path/to:my-test@ # Old behavior (gate off)
just stream-test //path/to:my-test@all-autogates # New behavior (gate on)