Every flag in Trunk belongs to the delta that added it. Toggle on, ramp to 10%, split A/B — all from the same tab you shipped from. The signal that validates the flag is one link away, not in a separate tool with a separate login.
Postal-code-first address entry with autofill. Rolled out gradually so each stage's TTFB signal clears before advancing.
Wrap new code in a flag and merge to main. The code is in production but off. Flip it on for yourself, then 10%, then everyone — from the same tab that owns the delta.
No separate flag vendor. No copy-pasting flag keys between dashboards. When the flag is retired, Trunk opens a cleanup delta that removes the wrapper.
// One import — same SDK as Signals import { trunk } from "@trunk/sdk"; // Wrap the new code path in a flag if (trunk.flag("cart.empty_state_v2")) { return <EmptyStateV2 />; } return <EmptyStateV1 />; // A/B — Trunk splits, tracks, and picks a winner const variant = trunk.experiment("header.semantic_v2"); return variant === "B" ? <HeaderB /> : <HeaderA />;
Every flag in Trunk fits one of three shapes. Each one is tied back to the delta that added it and the signal that will validate it.
Ship code dark, flip on when ready. One click reverts if a Signal alerts. The kill is the flag — no revert PR, no redeploy.
Ramp 1% → 10% → 50% → 100%. Each stage's advance gate is a Signal — no click-through until the numbers say so.
Split traffic across variants. Trunk runs the stats and files a "graduate winner" delta when the interval clears.
Trunk creates the flag when the delta enters Code phase, ramps it when a Signal clears the gate, and files the cleanup delta when the flag has been at 100% for the retention window. No orphan flags. No dead code paths.
A flag without a delta is dead code waiting to happen. A flag without a signal is a guess. See how flags tie into the rest of Trunk.