This guide shows you how to release a feature gradually — for example to 10% of sites first, then 50%, then 100% — using feature flags.
npm install @forge/feature-flags@latestBefore writing any code, decide what you're rolling out to: sites or users.
| Goal | ID type to use |
|---|---|
| Roll out to X% of Atlassian sites | installContext |
| Roll out to X% of users within each site | accountId |
Rolling out by site is simpler — all users in a site get the same experience. Rolling out by user allows finer control but means different users in the same site may see different behaviour.
When creating the flag in Developer Console:
installContext for site-level rolloutsaccountId for user-level rollouts1 2import { FeatureFlags } from "@forge/feature-flags"; resolver.define('getFeature', async ({ context }) => { const featureFlags = new FeatureFlags(); await featureFlags.initialize({ environment: context?.environmentType?.toLowerCase() || "development" }); const user = { identifiers: { installContext: context?.installContext, }, attributes: { installContext: context?.installContext, } }; const isEnabled = featureFlags.checkFlag(user, "my-feature-flag", false); await featureFlags.shutdown(); return isEnabled; });
1 2import { FeatureFlags } from "@forge/feature-flags"; resolver.define('getFeature', async ({ context }) => { const featureFlags = new FeatureFlags(); await featureFlags.initialize({ environment: context?.environmentType?.toLowerCase() || "development" }); const user = { identifiers: { accountId: context?.principal?.accountId, }, attributes: { accountId: context?.principal?.accountId, } }; const isEnabled = featureFlags.checkFlag(user, "my-feature-flag", false); await featureFlags.shutdown(); return isEnabled; });
10)90)The SDK randomly assigns each installContext or accountId to pass or fail based on these percentages. The assignment is consistent — the same site or user always gets the same result for a given percentage configuration.
To widen the rollout, update the percentage in Developer Console:
10 to 50)The change takes effect within 60 seconds for existing instances of the server-side SDK (its polling interval). The client SDK picks up the new configuration on next initialization.
Percentage updates are manual — there's no automated time-based progression. See Limitations for details.
Once you're confident in the feature, set Pass to 100% and Fail to 0%. At this point, the flag is effectively permanent — you can clean it up:
checkFlag call from your codeRate this page: