Feature Flags & A/B Testing
Grit ships an in-memory feature-flag engine with sticky bucketing, percentage rollouts, allow/blocklists, and realtime push when an admin toggles a flag. It lets you decouple deploy from release — merge code whenever, turn it on when you're ready.
Reference docs: Feature Flags →
Flags vs deploys
Ship code dark, then turn it on for whoever you choose — no redeploy.
Percentage rollouts
Release to 1%, then 10%, then everyone, watching Pulse as you go.
Sticky bucketing
A user always lands in the same variant, so the experience stays consistent.
Realtime push
Toggle a flag in the admin and connected clients update without a refresh.
Why feature flags?
A feature flag is a runtime switch that decides whether a piece of functionality is active. Wrap new code in a flag and you can merge it to main immediately, keep it off in production, then enable it for internal users, then 5% of traffic, then everyone — all without shipping new code.
Checking a flag
On the server, gate logic behind flags.IsEnabled. The request context carries the current user, which the engine uses for sticky bucketing.
func (h *CheckoutHandler) Create(c *gin.Context) {
if flags.IsEnabled(c, "new_checkout") {
h.newCheckout(c)
return
}
h.legacyCheckout(c)
}On the client, the generated hook reads the same flags and re-renders when an admin pushes a change over the realtime hub.
const newCheckout = useFlag('new_checkout')
return newCheckout ? <CheckoutV2 /> : <CheckoutV1 />Rollouts & targeting
| Control | Effect |
|---|---|
| Enabled toggle | Master on/off for the flag |
| Percentage | Share of users who get it (sticky) |
| Allowlist | Always-on for these users |
| Blocklist | Always-off for these users |
Practice
Challenge: Gate a feature
Wrap any handler branch behind flags.IsEnabled(c, "my_feature"). Create the flag in the admin with the toggle off. Confirm the old path runs, then flip it on and confirm the new path runs.
Challenge: Roll out to 10%
Set the flag to a 10% rollout. Hit the endpoint as several different users. Roughly what fraction get the new path? Does the same user always get the same result?
Challenge: Allowlist yourself
With the percentage at 0%, add your own account to the allowlist. Do you see the feature while everyone else doesn't? Which wins — the allowlist or the percentage?
Challenge: Watch the realtime push
Open the client page that uses useFlag. With the page open, toggle the flag in the admin. Does the UI change without a manual refresh? What mechanism makes that happen?
Enjoying the course?
Help us grow, star us on GitHub, subscribe on YouTube, and follow on LinkedIn.
