SOLENOID.SYSTEMS [...]
SYS ENG PHI PRICING
API
├─ CATCH ├─ GATE ├─ KEY ├─ LATCH ├─ METER ├─ PULSE ├─ RELAY └─ WITNESS

The Feature Flag Tax: Why Simple Beats Powerful

#feature-flags #simplicity #gate #architecture

Feature flags started simple. Ship code behind a boolean. Flip it on when ready. Flip it off if something breaks.

Then the platforms got ambitious.

Now you can target by user segment, percentage rollout, geographic region, device type, custom attributes, time windows, and combinations thereof. The dashboard has more options than your actual product.

And somewhere along the way, a tool meant to reduce deployment risk became its own source of complexity.

The Hidden Costs

Every targeting rule is technical debt. Six months from now, someone will ask “why does this flag have a 73% rollout to users in EMEA with premium subscriptions created before March?” Nobody will remember.

Every flag evaluation becomes a decision tree. Latency creeps up. You add caching to compensate. Now you have cache invalidation bugs and stale flag states.

The dashboard becomes a second codebase. Non-engineers make targeting changes. Engineers aren’t sure what’s actually running in production. The flag system that was supposed to give you confidence now gives you uncertainty.

What Most Teams Actually Need

Look at your flags. Count how many use advanced targeting versus simple on/off. For most teams, it’s 90%+ boolean.

The complex flags are usually:

  • Gradual rollouts that should have completed months ago
  • A/B tests that should be in a proper experimentation platform
  • User segmentation that belongs in application logic, not flag configuration

The platform sold you flexibility. What you needed was a light switch.

A Minimal Alternative

Gate is boolean-only. Every flag is enabled: true or enabled: false. No targeting rules. No percentage rollouts. No segments.

const gate = new GateClient({ apiKey: 'sm_your_key' })
await gate.sync()

if (gate.isEnabled('new_checkout_flow')) {
  renderNewCheckout()
} else {
  renderLegacyCheckout()
}

The SDK syncs flags on startup (and periodically after), then evaluates locally. No network call per check. Check flags in hot paths without latency concerns.

The Tradeoff

Flag changes take effect on next sync—typically 30-60 seconds. This is the tradeoff for local evaluation performance.

For most use cases, this delay is fine. You’re not doing real-time A/B testing. You’re not doing instant kill switches (though you could reduce the sync interval for critical flags).

If you need sub-second flag propagation with complex targeting, Gate isn’t for you. Use LaunchDarkly or Split. Pay the complexity tax. Just know you’re paying it.

Implementation Simplicity

Gate stores flags in Cloudflare KV, namespaced per account:

gate:{account_id}:dark_mode → {"enabled": true}
gate:{account_id}:new_pricing → {"enabled": false}

No relational database. No complex query patterns. Key-value lookup at the edge. Flag creation is a PUT. Flag check is a GET. Flag deletion is a DELETE.

The entire API is four endpoints. The mental model fits in your head.

When Minimal Works

Gate is right when:

  • You ship features behind flags and enable them when ready
  • You want kill switches for new code paths
  • You need to disable features during incidents
  • Your flag logic is “on or off,” not “on for some users”

Gate is wrong when:

  • You need percentage rollouts for gradual releases
  • You’re running A/B tests and need statistical rigor
  • You have complex targeting requirements by user attributes
  • You need real-time flag propagation (< 1 second)

The Price of Simplicity

Gate’s free tier gives you 10,000 API calls to evaluate. Starter tier ($19.99/mo) and above? Unlimited Gate usage.

For most teams going to production, Gate becomes a non-factor in your bill. Pay once, use as much as you want.

Your feature flag bill becomes predictable. Your flag system becomes understandable. Your deploys become less stressful.

Sometimes the best feature is the one you didn’t add.