Harden your workflow
You finished the quickstart. You have one TOML file, a flag, and an eval_string call site. That's enough to ship — for a side project. Six chapters turn it into a reviewable, testable, observable change process you can take to production.
The thread through all six is one realistic flag — a three-variant string with a percentage-bucketed A/B/C rollout, scoped to US users only. Every chapter operates on the same flag, so once you've finished one chapter, the next one picks up where you left off.
Chapters
-
Define the flag namespace. Write a realistic flag with three variants, three bucket segments, and a US-only geo gate. Run
exd explainonce to verify the whole shape — variants, rule walk, segment tree, required context, pitfalls — before another tool touches it. -
Lint on every commit and every PR. Wire
exd lintinto a pre-commit hook and a GitHub Actions workflow. Typos, dangling segment references, and shape errors get caught before the diff reaches a reviewer. -
Schema-driven application code. Run
exd schemato learn what context the flag reads, codegen a typed context struct, and write the eval call site. Add a one-linevalidate_contexttest so the application and the manifest cannot drift apart silently. -
Fixtures and automated tests. Run
exd fixturesto generate a(ctx, expected variant)table from the rule chain. Eyeball it for correctness, commit it, and consume it from a fixture-driven test that runs on everycargo test/npm test. -
Roll out with the
testingattribute. Walk a flag through Disabled → Testing → Enabled. Whiletesting = trueis on, only callers that passinclude_testingsee the new rules — so dev and admin can run end-to-end tests in production while regular traffic still sees the off variant. Drop the gate when you're happy; the rules go live. -
Troubleshoot with
exd eval. "Why did useru_123get the off variant last night?" Reconstruct the evaluation withexd eval --trace, layerexd explain --ctxfor counterfactuals, and walk through the common diagnostic patterns (missing bucketing attribute, wrong env, predicate-type mismatch).
Prerequisites
- Quickstart complete:
marketing/flags/welcome-banner.tomlexists, your Rust or TS code evaluates it. - The
exdCLI on PATH:cargo install exd-client(one binary; used by both Rust and TS projects). - A git repo. The pre-commit hook and CI examples assume it.
Where everything sits
A flag namespace is a directory whose name is the namespace slug, holding flags/ and segments/ inside it (see docs/reference/manifest/01-directory-layout.md). When you colocate flags with an application, the namespace directory sits as a child of the application repo — never as the repo:
<your-app-repo>/ # application repo root (name is yours; not the slug)
├── marketing/ # flag namespace; slug = "marketing"
│ ├── flags/
│ │ └── welcome-banner.toml
│ └── segments/
│ ├── welcome-banner-bucket-control.toml
│ ├── welcome-banner-bucket-treat-a.toml
│ └── welcome-banner-bucket-treat-b.toml
├── src/ # your application source
│ └── ...
├── tests/
└── .git/
The directory name (marketing/) is the namespace slug — exd infers it directly, so no namespace.toml is needed at this stage. All exd commands point at the namespace directory, not the repo root — exd lint marketing/ from the repo root, or cd marketing/ && exd lint . if you prefer.
Once a second service needs the same flags, the marketing/ directory lifts cleanly out of the app repo into a dedicated feature-flags repo — see Centrally hosted flag namespace. The migration is a literal git subtree split --prefix=marketing; the file contents stay the same.
Where to go next
- Rung 2 — central flag namespace. Move flags out of the application repo into a dedicated git repo shared across services and teams. See Centrally hosted flag namespace.
- Telemetry. Pipe evaluation records to a sink, then run
exd telemetry srm | rules | dead-flagsto catch rollout pathologies before users do. See Telemetry reference. - Reference. Linter rules ·
exdCLI · Rust SDK · TypeScript SDK.