flag-drift-audit
Multi-environment feature-flag setups drift silently: a flag gets added in staging and forgotten in production, a rollout percentage gets bumped in one environment and not another, or a flag outlives its purpose and nobody removes it. These are the JSON exports most flag providers already let you download - this project diffs them properly.
What it detects
- Missing flags - present in one environment, absent from another
- Value drift - a flag exists everywhere but its default value or rollout percentage differs across environments
- Stale/orphaned flags - flags marked
"unused": true, or untouched for longer than a configurable threshold vialastModified
Usage
flag-drift-audit [options] <env1.json|dir> <env2.json|dir> [...more envs]
Two environments:
node bin/flag-drift-audit.js fixtures/staging.json fixtures/production.json
Three or more environments, or a directory of exports:
node bin/flag-drift-audit.js fixtures/staging.json fixtures/production.json fixtures/development.json
node bin/flag-drift-audit.js ./flag-exports/
See examples/ for worked comparisons with checked-in expected output,
including a realistic multi-flag, multi-environment scenario in
examples/realistic/.
Example output
Console report for fixtures/staging.json, fixtures/production.json, and
fixtures/development.json compared together:

Options
| Flag | Description |
|---|---|
-f, --format <console|json|markdown> |
Report format (default: console) |
-o, --output <path> |
Write the report to a file instead of stdout |
--stale-days <N> |
Age threshold for stale flags (default: 90) |
--ignore-keys <a,b> |
Comma-separated flag keys to ignore in drift comparison |
--strict |
Fail if any config has an invalid flag shape |
--fail-on-drift |
Exit with code 2 if drift is found |
--no-color |
Disable ANSI color in console output |
-h, --help |
Show help |
-v, --version |
Show version |
CI usage
Gate a pipeline on flag drift with --fail-on-drift, which sets exit code
2 when any missing or drifted flags are found (1 on usage errors, 0
when clean):
flag-drift-audit --fail-on-drift staging.json production.json || exit 1
See examples/ci-usage.yml for a copy-pasteable GitHub Actions job.
Use as a GitHub Action
- uses: aks-builds/flag-drift-audit@main
with:
files: flags/staging.json flags/production.json
fail-on-drift: "true"
format: markdown
Directory input
Instead of listing files, point at a directory of exports and each
*.json file inside becomes one environment:
flag-drift-audit ./flag-exports/
Exit codes
| Code | Meaning |
|---|---|
| 0 | No usage error; drift may or may not have been found |
| 1 | Usage error (bad arguments, fewer than two files, unreadable/invalid config) |
| 2 | --fail-on-drift was set and drift or missing flags were found |
Troubleshooting
- "Cannot read config file" - the path does not exist or is not readable; check for typos or permissions.
- "Invalid JSON in ..." - the file is not valid JSON; open it in an editor with JSON linting to find the exact syntax error.
- Directory produced 0 environments - the directory has no JSON files directly inside it (subdirectories are not scanned recursively).
- "Cannot write report to ..." - the
--outputpath's parent directory does not exist; create it before running the command.
Status
1.0.0: the CLI surface is stable. Drift, stale-flag detection, and strict
validation work end to end against fixture, example, and realistic
multi-environment configs, with console, JSON, and Markdown report formats
and optional file output via --output.
Tags
feature-flags devops cli config-drift release-engineering