Skip to content

Feature Toggles

Open in ChatGPTOpen in Claude

Every construct group in an Axis project is behind a typed toggle. Off means not instantiatedcdk/bin/app.ts reads the resolved toggle set and only creates the stacks and construct groups whose flags are true. Nothing is ever half-deployed; a group is in the app or it isn’t.

A manual-wiring project declares its toggles in one file: a FeatureToggles interface, a DEFAULT_FEATURES constant, and a resolveFeatures(app) resolver. The rest-v1 starter carries the full set — the same one the framework’s own example-rest-full ships, included here verbatim from that synth-tested source:

export const DEFAULT_FEATURES: FeatureToggles = {
dynamo: true,
sqs: true,
sns: true,
kms: true,
s3: true,
secrets: true,
waf: true,
ses: true,
eventBridge: true,
observability: true,
budget: false,
negative: false,
};

dynamo is the data layer and is mandatory — the resolver throws if it is turned off, because half the app depends on it. budget defaults off (it is account-global) and negative defaults off (it wires synth-throw guard cases used only by the test harness). Leaner starters carry leaner sets — rest-v2 has a single httpApi toggle, bare a single dynamo toggle (turn it off and the project synths as one Lambda and nothing else), and worker has dynamo, sqs, and observability.

Flip at synth time — --context feature.<name>=on|off

Section titled “Flip at synth time — --context feature.<name>=on|off”

The resolver overlays defaults with CDK context, so any toggle set is one synth away without touching a file:

Terminal window
cdk synth --context feature.observability=off

An invalid value throws an [Axis] error instead of silently defaulting — a typo cannot pass unnoticed. This overlay is the day-to-day debugging tool the harness was built for: flip a group off, re-synth, and see exactly what changes.

axs new prompts one yes/no per optional group and writes your answers into DEFAULT_FEATURESno code is pruned. The rewrite touches only the constant’s boolean literals; comments, types, and the resolver are preserved verbatim. That makes every create-time “no” fully reversible: edit the constant, or override with context.

Mandatory groups are forced on and never prompted for — dynamo on rest-v1 is the data layer, and its resolver throws if you try to turn it off, because half the app depends on it.

axs feature is the assisted editor for the same file:

Terminal window
axs feature # view the current toggle table
axs feature sqs=off -y # set one or more toggles
axs feature # (no args, TTY) interactive multiselect edit

It writes through the exact same safe block-rewrite used at scaffold time, and mandatory groups render locked in the UI — the command cannot produce a features.ts that fails at synth. --explain <name> and --dry-run <name>=off give read-only views of a toggle’s dependency edges and what a removal would touch. See the axs feature reference.

A composer project has no config/features.ts — its canonical state is the selections block in axis.json, and deselected features have their config removed rather than flag-flipped (axs feature <name>=off performs a guarded removal there, with the same --dry-run preview). The synth-time context overlay works the same way in both worlds, with one deliberate restriction: context maps to on/off only and cannot target a stack whose mode is "custom" — substituting a stack is project state, not a synth experiment.

© 2026 Axis Tech. Powered by axis-tech.co.