You’re three weeks out of YC Demo Day. The product works. Mostly. You ship a small fix to checkout on a Tuesday afternoon and ten minutes later your only paying customer Slacks: “is this supposed to be broken?”

Welcome to the start of the feature flag journey. Almost nobody plans this journey. Everybody takes it.

Here’s the map.

The six levels of feature flag maturity, from cowboy push-to-prod to a managed flag service

Level 0 — Cowboy Mode

There are no flags. There is no staging. main is production. You merge a PR and forty seconds later your customers are the QA team.

This is fine for about six weeks. It is glorious, actually. You ship five times a day, the whole team fits in a Discord channel, and rolling back means git revert and a fresh npm run deploy.

Then one of three things happens:

  1. A bad deploy takes down checkout during a demo with a prospect.
  2. A half-finished feature gets shipped because someone’s branch got merged early.
  3. You hire your fourth engineer and suddenly two PRs collide.

You don’t choose to leave Level 0. Level 0 evicts you.

Level 1 — The Hardcoded if

Welcome to the Boolean Era.

const NEW_CHECKOUT = false;

if (NEW_CHECKOUT) {
  return renderNewCheckout();
}
return renderLegacyCheckout();

This works. Briefly. The new flow is hidden behind a constant that you flip when you’re ready to ship.

The cracks show up fast:

  • Flipping the flag requires a deploy. So your “instant rollback” is a 4-minute build and a held breath.
  • You can’t enable it for one user. Your designer has to wait until everyone gets it.
  • Six months later there are 14 of these constants scattered across the codebase and nobody remembers which ones are still meaningful.
  • The “off” branch is dead code that subtly rots until the day you delete it and discover it wasn’t actually dead.

Adjacent variant: commenting out the new code. Don’t.

Level 2 — Env Vars and Config Files

You promote the booleans to environment variables. Now ENABLE_NEW_CHECKOUT=true lives in your deployment config. Maybe there’s a YAML file. Maybe a config.production.json.

This is a real upgrade. You can have different values per environment. Staging gets the new thing, prod doesn’t. Toggling no longer requires a code change — just a deploy of new config.

It also has hard ceilings:

  • Still requires a deploy (or pod restart) to change.
  • No targeting. It’s on for everyone or off for everyone.
  • Anyone with prod access can change it. There is no audit trail of who flipped what when.
  • Nobody on the product or growth team can touch it without filing a ticket.

This works until your CTO is on a flight and a junior engineer needs to disable a misbehaving feature right now.

Level 3 — The Homegrown DB Toggle

This is where most startups land. And get stuck.

Someone — usually the most senior backend engineer, usually on a Saturday — builds a feature_flags table.

CREATE TABLE feature_flags (
  key TEXT PRIMARY KEY,
  enabled BOOLEAN NOT NULL DEFAULT FALSE
);

Then a tiny admin page. Then a helper:

async function isEnabled(key: string): Promise<boolean> {
  const row = await db.query("SELECT enabled FROM feature_flags WHERE key = $1", [key]);
  return row?.enabled ?? false;
}

Glorious. Real-time toggles. No deploy. The product team feels powerful for about three weeks.

Then reality lands:

Performance. That isEnabled() call hits the database on every request. You add a 30-second in-memory cache. Now toggles take 30 seconds to propagate, and they propagate at different times across your fleet. Two users on adjacent servers see different versions of the app. Support tickets get weirder.

Targeting. Marketing wants to enable the new pricing page for users in the EU. You add a targeting_rules JSON column. Six months later it has 11 fields, three undocumented operators, and one engineer who understands it. He’s interviewing elsewhere.

Access control. Anyone with prod database access can toggle anything. There are no roles. There are no environments — staging and prod share the same table, or they don’t, and nobody documented which.

Audit. Someone disabled enable_async_invoicing at 3am on a Sunday. Was it Priya? Was it the deploy script? Was it the accidental UPDATE without a WHERE clause? Nobody knows. You add an audit_log table. It works for a month, then someone forgets to write to it from a new code path.

SDK debt. You wanted to use these flags from the React app. So now you also have a /api/flags endpoint. It returns all flags for the user. Including the ones gating internal admin features. Whoops.

The graveyard. Two years in you have 240 flags. Twelve of them are actually checked in code. The rest are tombstones. Nobody knows which is which. Removing one is a four-hour archaeological dig.

Level 3 is seductive because each individual fix is small. The cumulative system is a load-bearing pile of duct tape. You will feel the weight before you can see it.

Level 4 — The Open-Source Service

You install Unleash. Or Flagsmith. Or GrowthBook. You self-host it on a small box, you point your services at it, and suddenly you have a real UI, real targeting rules, real audit logs, and a real SDK.

This is a genuinely large step up. For a lot of teams, this is the right answer for a long time.

The honest tradeoffs:

  • You now run a service. It needs upgrades, backups, monitoring, an on-call rotation. Your “free” feature flag system costs about half a backend engineer-week per quarter.
  • Performance is yours to own. The SDK caches help, but if your eval server hiccups, your app hiccups. You’ll learn what a streaming SDK is and then you’ll learn what happens when it disconnects.
  • Scaling targeting. When you get past a few hundred flags and a dozen environments, the UX of most OSS dashboards starts to bend.
  • Integrations. You’ll wire up Slack notifications yourself. And the Datadog exporter. And the Terraform provider, if it exists.

If you have the engineering bandwidth and the data-residency requirements that make self-hosting non-negotiable — this is a great place to be.

Level 5 — A Managed Flag Service

You stop running the thing and start using the thing.

A managed flag service gives you what Level 4 gives you, minus the on-call, plus:

  • Sub-millisecond evaluation at the edge instead of a round-trip to your self-hosted box.
  • Mature targeting (segments, percentage rollouts, mutually exclusive experiments, scheduled rollouts) without you maintaining the rule engine.
  • SOC 2, audit trails, role-based access control, and SSO that the security team actually accepts.
  • Lifecycle tooling — staleness detection, owners, expirations — so the flag graveyard doesn’t reappear.
  • An SDK story that includes the languages you forgot you used.

The honest tradeoff: you’re paying someone. And many of these vendors are priced for a Series C company that has forgotten what early-stage feels like. Per-seat pricing, per-MAU pricing, “contact sales” pricing, six-figure floors.

This is why Level 3 sticks around. The jump to Level 4 costs engineering time you don’t have. The jump to Level 5 costs money you don’t want to spend on a sales call.

Where Should You Actually Be?

Honest answer:

StageRight level
Pre-PMF, 1–3 engineersLevel 1 or 2 is fine. Don’t over-invest.
First paying customers, 3–8 engineersLevel 2 is the floor. Level 3 only if you can keep it tiny.
Scaling team, multiple environments, real customersLevel 4 or 5. Level 3 is now a liability.
Compliance customers, multiple productsLevel 5. The audit story alone pays for it.

The mistake isn’t being at the wrong level. The mistake is staying at Level 3 because moving feels expensive, while the duct tape quietly compounds.

A Plug, Honestly Stated

We make a flag system. It is, naturally, a Level 5 thing.

We don’t think you need us on day one. If you’re two engineers shipping to twelve users, an environment variable is the correct tool. If you’ve built a tight Level 3 system that fits your needs, keep it. If Unleash or GrowthBook is working — that’s a great choice and we’ll happily help you migrate later if you ever outgrow it.

What we’re trying to do is take the cost out of moving up a level. ShipSilently is:

  • Cheap to start. A free tier that’s actually usable, not a 14-day trial.
  • Easy to adopt incrementally. Drop the SDK in next to your existing flags. Migrate one flag at a time. We have migration guides for the major systems.
  • No vendor lock-in. Standard semantics, exportable config, no proprietary DSL. Leave whenever you want.
  • No “talk to sales.” Self-serve everything. Pricing is on the pricing page. The contact form goes to actual humans who write code.

If you’re at Level 3 and feeling the weight, or at Level 4 and tired of being on-call for your flag service, give us a try. If you’re at Level 0 having a great time — keep going. We’ll be here when you’re ready.

The right moment to upgrade your flag system is the moment before you wish you had.


Build feature flags that scale with you, not the other way around. Start free with ShipSilently — no credit card, no sales call, no lock-in.