Ben Price

Reviving the Blog, and Introducing Flags.md

· 15 min read · Building in Public

Reviving the Blog, and Introducing Flags.md

Blog Revival

It has been a while since I wrote anything here.

Like a lot of side projects, writing quietly fell behind everything else. Work got busy. Life got busy. Building got busy. I kept meaning to come back to this blog, but I did not want to revive it just to post updates for the sake of posting updates.

I wanted to have something real to talk about.

Not just an idea. Not just vague intentions. Something I was actively building, making decisions on, changing my mind about, and pushing closer to reality.

That thing is Flags.md.

This blog revival is going to be more build in public than what I have done before. Not in the sense of turning every tiny update into content, but in the more useful sense of sharing the actual decisions behind the product while it is still taking shape.

A lot of those decisions are already made.

  • The architecture is largely set
  • The pricing model has been worked through in detail
  • The MVP is essentially feature complete
  • The first pass of the TypeScript SDK is done
  • The next step is internal alpha testing before going live

So in a way, I am slightly late to the whole “sharing the process” part.

That is fine.

There is enough here now to say something interesting.

This is the reset. The blog is back, and Flags.md is the reason.


New Project: Flags.md

Flags.md is a feature flags platform built for teams that want modern rollout control without the weight, complexity, and pricing nonsense that has become normal in this category.

Why I started building it

The truth is, I did not start building Flags.md because I woke up one day wanting to enter the feature flag market.

I started building it because I wanted it for myself.

I am also working on Kiboh.io, and while thinking through release control, experimentation, progressive rollout, and operational safety there, I ended up looking seriously at the existing feature flag platforms on the market.

I was not happy with what I found.

Some of the products were solid technically. Some were clearly mature. But the pricing felt wildly out of step with what they were offering, especially for indie developers, solo founders, and early-stage bootstrappers.

That was the part that really stuck with me.

The pattern felt familiar:

  • offer a free tier that is just useful enough to get you integrated
  • become part of the product architecture
  • let switching costs start working in their favor
  • then hit you hard once you outgrow the free limits

I get why companies do this. I really do. But as someone building products in the real world, it felt frustrating. I was not seeing many options that felt genuinely friendly to smaller teams or early-stage builders. There were plenty of platforms willing to let you start for free. There were far fewer that felt fair once your project became real.

That gap is what pushed me to build Flags.md.

What I want Flags.md to be

Flags.md is my attempt to build the feature flags platform I wanted to use.

That means a few things:

PrincipleWhat it means
Fair pricingNo “free until we got you” feeling
Fast evaluationFlags should feel invisible in the hot path
Real tenant isolationNot just an application-level promise
A path for smaller buildersIndie developers and early-stage teams should have a viable option
Room to growThe platform should still support more mature teams over time
Less unnecessary weightStrong rollout control without bloated complexity

I am not trying to build the biggest, most enterprise-looking platform on day one.

I am trying to build something that feels lighter, more modern, and more honest.

Not toy-like. Not shallow. Just more aligned with how I think software teams actually want to ship.


Architecture

One of the biggest early choices was building Flags.md on Cloudflare instead of taking a more traditional cloud path.

Why Cloudflare

Feature flags are a very specific kind of workload.

They are:

  • read-heavy
  • latency-sensitive
  • global by nature
  • often in the hot path of application behavior

That pushes you toward an architecture where runtime evaluation needs to be fast and predictable, while control plane operations still need strong consistency and clear ownership.

Cloudflare felt like a strong fit for that shape of problem.

High-level architecture

At a high level, Flags.md is split into three layers:

LayerResponsibilityStorage / Runtime
Control Planetenant lookup, billing, provisioning, plan metadataD1
Tenant Data Planeflags, environments, rollouts, segments, approvals, tenant audit indexesSQLite-backed Durable Objects
Long-term Audit Storageimmutable audit payloads, exports, archivesR2

How the pieces fit together

Control plane

The control plane handles platform-level metadata such as:

  • tenant slug
  • billing state
  • subscription plan
  • account ownership
  • tenant provisioning
  • control-plane mappings

This is shared platform metadata, not tenant operational state.

That is why it can live in D1.

Tenant operational state

All tenant operational data lives in tenant-isolated SQLite-backed Durable Objects.

That includes:

  • flags
  • variants
  • environments
  • targeting rules
  • segments
  • rollouts
  • approvals
  • runtime configuration state
  • tenant-scoped audit indexes

This is the authoritative source of truth for each tenant’s actual product state.

Audit history

Long-term canonical audit payloads live in R2.

That keeps historical log growth from eating into the storage limits of the tenant Durable Objects, while still letting the system preserve tenant-scoped indexing and search inside the tenant boundary itself.

The rule that guided the architecture

A simple rule ended up shaping a lot of the system:

  • Durable Objects own correctness
  • The distributed evaluation path owns speed

That sounds neat as a summary, but it has real implications:

  • writes go through a clear tenant authority
  • tenant state ownership is explicit
  • runtime evaluation can stay fast
  • audit history can scale separately from operational state

I like architectures that have a clear answer to “who owns what?” This one does.

Why not a traditional cloud stack?

There is definitely a version of this product that could have been built on a more traditional stack.

If I had gone that route, I probably would have looked seriously at:

  • Go for core services
  • a more conventional FaaS or service deployment
  • centralized databases plus caching
  • more explicit regional deployment strategy
  • more infrastructure work to get closer to edge-native behavior

That path has real strengths. Go is a great fit for backend systems, and I still think a compiled language would have been attractive for parts of the platform.

But for this problem, I did not want to spend a large part of the project rebuilding the properties I wanted from the start.

Cloudflare let me begin from an edge-native model instead of gradually approximating one.

That was a big reason I chose it.

The tradeoff

The clearest tradeoff is language and ecosystem.

Once you build deeply into Workers and Durable Objects, the world starts to pull you pretty hard toward TypeScript. In a vacuum, I would not automatically choose TypeScript as the foundational language for a backend-heavy infrastructure product. In a more traditional service environment, I might well have chosen Go for at least a meaningful part of the stack.

But Cloudflare’s V8-based runtime changes the equation in an important way.

One of the biggest advantages of Workers is avoiding the kind of cold start baggage that still hangs around older serverless mental models. That makes the trade feel much more reasonable.

So the tradeoff looks something like this:

ChoiceUpsideCost
Cloudflare + TypeScriptedge-native execution, strong platform fit, fast iteration, very low cold start concernsless flexibility in language/runtime choices
Traditional cloud + Gocompiled language, strong backend ergonomics, familiar service patternsmore infrastructure glue, more work to get globally fast behavior

For Flags.md, I think the Cloudflare path was the right one.

If I were making the same decision again today, I would still choose it.


Pricing

I have spent an almost embarrassing amount of time thinking about pricing for Flags.md.

Part of that is because pricing is hard. Part of it is because this market gives you a lot to react against. And part of it is probably the lingering effect of recently finishing my MBA, where I spent plenty of time staring at pricing strategy, margins, segmentation, contribution economics, and the many ways a business can talk itself into believing its pricing makes sense.

That background definitely did not help me spend less time on this.

If anything, it made it impossible not to think about the product through both lenses at once:

  • what feels fair to the customer
  • what actually works as a business

That tension is where Flags.md pricing came from.

What I disliked about the market

When I looked at a lot of the existing feature flag tools, the pattern felt pretty obvious.

PatternWhy it bothered me
Generous enough free tier to get integratedSwitching costs start working in the vendor’s favor
Sharp pain once limits are hitPricing jumps feel more extractive than supportive
Complex pricing structuresHard to predict bills and compare plans
Weak options for smaller buildersIndie teams and bootstrappers get squeezed early

That is the exact feeling I wanted to avoid.

I do not mind charging money. I want Flags.md to be a real business, not a charity project. I want it to make money. I want the margins to be healthy. But I want the pricing to feel fair.

Fair does not mean cheap for the sake of cheap. It means understandable, rational, and not built around trapping people.

The pricing model

Flags.md is priced on two usage dimensions:

  • evaluations
  • tracked events

That split exists because the product itself has two different kinds of value and two different kinds of cost profile.

Usage typeMeaning
EvaluationsRuntime feature flag checks
Tracked EventsExposure, conversion, and related analytics events

The current ladder looks like this:

PlanPriceEvaluationsTracked EventsProjectsEnvironmentsSeats
Free$075k / month10k / month111
Indie$9 / month1M / month50k / month331
Starter$19 / month5M / month250k / monthUnlimited35
Growth$49 / month20M / month1M / monthUnlimited315
EnterpriseFrom $799 / monthCustomCustomCustomCustomCustom

Overage philosophy

Overages are where pricing trust usually gets destroyed, so I wanted them to be simple and intentional.

The current self-serve overage rates are:

  • $2.25 per additional 1M evaluations
  • $10 per additional 1M tracked events

Those numbers were chosen to do a few things at once:

  • preserve strong margins
  • stay comfortably below competitor overage pricing
  • create a natural upgrade incentive
  • avoid feeling punitive

For example:

ScenarioResult
Indie customer hits Starter-level usageTotal bill lands around $20
Starter customer hits Growth-level usageTotal bill lands just over $60

That second one was deliberate.

There is a small but real psychological difference between paying something in the fifties and seeing a bill that starts with a six. Crossing that line makes the $49 Growth plan feel obviously like the smarter long-term choice, without turning overages into a punishment.

That kind of thing probably sounds like exactly the sort of pricing psychology discussion an MBA student would get dragged into in class, and honestly, yes, it is. But it matters. Pricing is not just arithmetic. It shapes customer behavior. It tells people whether you are trying to guide them toward the right plan or squeeze them once they are committed.

My aim with Flags.md is the former.

Features matter too

Usage alone is not enough to create healthy plan boundaries.

A big part of the Indie to Starter jump comes from features and team shape, not just traffic. That is intentional.

TierMain identityKey upgrade drivers
Freesandbox / hobbybasic entry point
Indiesolo productionmore projects, more environments, more real usage
Startersmall team productionseats, scheduled rollouts, webhooks, service accounts
Growthmature team workflowsapprovals, ownership, notifications, longer retention
Enterprisegovernance and custom needssecurity, compliance, support, custom terms

That helps the pricing feel more honest. A solo developer should not have to pay for a pile of team features they do not need. A growing team should have a clear reason to move up beyond just raw usage numbers.

The goal

The goal is simple:

Build pricing that is fair to customers, fair to the business, and hard to describe as “they got me in cheap and then gouged me later.”

That is the standard I want Flags.md to meet.


Next Steps

Flags.md is at a stage that feels very different from where it started.

This is no longer just architecture sketches and pricing spreadsheets. The MVP feature set is essentially there, and the first pass of the TypeScript SDK is done.

The next step is internal alpha testing.

What that means

The immediate focus is:

  • validating the end-to-end product experience
  • finding rough edges in the dashboard and workflows
  • pressure-testing the evaluation path
  • making sure the TypeScript SDK feels good in real use
  • checking that the pricing model still feels right against actual usage patterns
  • tightening anything that feels clever in theory but awkward in practice

This is one of the least glamorous parts of building, but also one of the most important.

A product can make perfect sense in architecture notes and still feel rough once it hits real workflows.

SDKs after launch

The TypeScript SDK was the obvious place to start, partly because of the architecture choices and partly because it fits the first audience I expect to serve.

But it is definitely not the end state.

Once Flags.md goes live, one of the next big priorities will be support for other popular languages. If the platform is going to be broadly useful, it needs a stronger SDK story beyond JavaScript and TypeScript.

That work comes after launch.

Where things stand now

So, today, the state of Flags.md looks like this:

AreaStatus
Product conceptvery real
Core architecturedecided
Pricing modeldefined
MVP feature setessentially complete
TypeScript SDKfirst pass done
Internal alphanext
Additional SDKspost-launch priority

That is a good place to be.

Still early, but no longer abstract.

And that is exactly why this feels like the right time to start writing again.


New posts delivered to your inbox. No spam, unsubscribe anytime.