Feature Toggles
Every construct group in an Axis project is behind a typed toggle. Off means not instantiated — cdk/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.
config/features.ts
Section titled “config/features.ts”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:
cdk synth --context feature.observability=offAn 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.
Where the defaults come from
Section titled “Where the defaults come from”axs new prompts one yes/no per optional group and writes your answers into DEFAULT_FEATURES — no 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.
The axs feature command
Section titled “The axs feature command”axs feature is the assisted editor for the same file:
axs feature # view the current toggle tableaxs feature sqs=off -y # set one or more togglesaxs feature # (no args, TTY) interactive multiselect editIt 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.
Composer projects are different
Section titled “Composer projects are different”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.