Why We Built Our Feature Flag System Instead of Paying for LaunchDarkly
At 137Foundry, we have evaluated a lot of tools in the feature management category over the years. LaunchDarkly, Unleash, Flagsmith, Split -- we have used several of these with clients and built with them internally. After running both the managed-platform path and the DIY path on multiple production projects, we consistently land in the same place for most applications: the custom implementation wins until the team hits 30 to 50 engineers actively using flags.
Here is our reasoning, and the specific cases where we change the answer.
The Managed Platform Pitch Is Real But Oversold
The value proposition for platforms like LaunchDarkly is genuine. You get a management dashboard, audit logs, per-user targeting, multi-environment support, SDK integrations for every major language, and a reliable API. For an enterprise team shipping to production 20 times a day, that operational tooling has clear value.
The pitch oversells, though, when it is directed at small and mid-size teams with straightforward rollout needs. Most applications need three things from a feature flag system: turn new code on and off, roll out to a percentage of users, and do both without a redeploy. Those three things take one database table and 50 lines of application code. They do not require a SaaS contract.
The real cost of a managed platform is not just the subscription fee -- it is the dependency. When you adopt LaunchDarkly's SDK, flag evaluation happens inside their library and their network requests. The flag system stops being your infrastructure and becomes an external service your application depends on. For flags that control critical application paths, that dependency matters.
What We Built and Why It Was the Right Call
For a recent client project we built at 137Foundry -- a mid-size SaaS application with a team of 8 engineers -- we implemented a custom feature flag system as part of the core application infrastructure. The full implementation: one PostgreSQL table, a 60-line Node.js evaluator with hash-based percentage bucketing, a Redis cache layer, and a React hook for client-side flag consumption.
Total implementation time: about 6 hours including tests and code review.
Total ongoing maintenance burden over 12 months: low. The system works, flags are created and retired on a schedule, and the whole thing is visible in the application codebase rather than in an external dashboard.
The complete implementation we use for these projects is documented on the 137Foundry blog. It covers the data model, the evaluator pattern (including the deterministic hash that prevents inconsistent per-user flag state), and the React integration. If you are building a new application or adding flags to an existing one, that guide is the starting point we give our own engineers.
What 12 Months of Custom Flag Operations Actually Looked Like
After shipping the custom flag system for that mid-size SaaS client project, the team used it in production for over a year. Here is what the operational reality looked like.
Flag volume stayed manageable. At the 12-month mark, the flags table had 23 rows. Fourteen were actively used, six had been permanently enabled and were candidates for cleanup, and three were operational toggles that would stay indefinitely. Managing 23 rows in a database is trivially easy. A managed platform would not have changed this.
Flag creation took two minutes. A SQL INSERT, a comment in the Slack deploy channel, and a calendar reminder for cleanup. The absence of a UI dashboard was not friction at this team size.
One rollback saved significant user impact. In month eight, a flag controlled a new billing calculation. At 5 percent rollout, the team noticed an edge case producing incorrect invoice totals for monthly-to-annual subscription upgrades. Rolling back was a single SQL UPDATE. The whole incident -- detection to resolution -- took eleven minutes. Without the flag, that bug would have hit all users simultaneously and required an emergency deploy to fix.
The only real limitation appeared at month ten. A new engineer on the project wanted to enable a flag for testing in their development environment without touching the shared staging database. The custom system had no per-environment flag isolation -- flags were global across all environments sharing the same database. The workaround was a development-only flag override in a local .env file. It worked, but it was friction that a managed platform would have solved natively.
That one limitation -- per-environment flag isolation -- is the most common trigger we see for teams moving to Flagsmith or LaunchDarkly. It is a real operational need, and the workaround is less clean than a proper solution. For teams that hit it, Flagsmith self-hosted is the most efficient path to resolving it without committing to a SaaS subscription.
The Hash-Bucketing Detail That Most Tutorials Skip
One thing we see wrong in almost every DIY feature flag tutorial is the percentage rollout implementation. The common mistake: generate a random number between 0 and 99 on each evaluation and check if it falls below the rollout percentage. This means the same user might see a feature on page load and not see it on the next API call -- fundamentally broken behavior.
The correct approach is to hash a stable input (flag key + user ID) to produce a deterministic bucket. Same inputs, same output, same flag state -- every time, for every user.
function stableHash(input) { let h = 0; for (let i = 0; i < input.length; i++) h = (h * 31 + input.charCodeAt(i)) >>> 0; return h % 100; }
This is a small implementation detail that has a large user-experience impact. Without it, 10 percent rollouts produce inconsistent behavior that looks like a bug. We have debugged this exact issue on client projects that used naive random-number implementations before coming to us.
When the Calculus Changes
We change our recommendation from "build" to "buy" in two scenarios:
The team is large and ships frequently. At 30+ engineers shipping to production multiple times a day, the absence of a management dashboard becomes a real operational friction. Engineers need to create and modify flags without database access, flag history needs to be auditable, and per-user targeting requirements tend to become more sophisticated. That is when LaunchDarkly or Flagsmith (self-hosted, for cost reasons) earns its place.
Experimentation is a primary use case. If the team is running A/B tests with statistical significance measurement as part of their growth workflow, a purpose-built experimentation platform like Split.io is meaningfully better than a custom flags table. The experiment analysis tools alone justify the cost at that point.
For everyone else -- and that is most development teams we work with -- the custom approach is the right default. Start there, understand your system, and reach for a managed platform when the operational complexity genuinely justifies it.
The Recommendation
If you are building a new web application or adding feature flags to an existing one, implement the custom approach first. Use the build guide on our site as the starting point. Set a review date at 6 months. If the flag system is causing friction, evaluate managed options at that point.
If you are inheriting an existing application with no flag system and you are under time pressure, Flagsmith self-hosted is the fastest path to a working management UI with reasonable self-hosting costs. LaunchDarkly is the right call if the team is large, compliance requirements are strict, and the subscription cost is not a constraint.
We are happy to dig into the specifics for any application architecture -- reach out through the app development services at 137Foundry if you are weighing these options.















