Reviving the Blog, and Introducing Flags.md
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:
| Principle | What it means |
|---|---|
| Fair pricing | No “free until we got you” feeling |
| Fast evaluation | Flags should feel invisible in the hot path |
| Real tenant isolation | Not just an application-level promise |
| A path for smaller builders | Indie developers and early-stage teams should have a viable option |
| Room to grow | The platform should still support more mature teams over time |
| Less unnecessary weight | Strong 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:
| Layer | Responsibility | Storage / Runtime |
|---|---|---|
| Control Plane | tenant lookup, billing, provisioning, plan metadata | D1 |
| Tenant Data Plane | flags, environments, rollouts, segments, approvals, tenant audit indexes | SQLite-backed Durable Objects |
| Long-term Audit Storage | immutable audit payloads, exports, archives | R2 |
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:
| Choice | Upside | Cost |
|---|---|---|
| Cloudflare + TypeScript | edge-native execution, strong platform fit, fast iteration, very low cold start concerns | less flexibility in language/runtime choices |
| Traditional cloud + Go | compiled language, strong backend ergonomics, familiar service patterns | more 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.
| Pattern | Why it bothered me |
|---|---|
| Generous enough free tier to get integrated | Switching costs start working in the vendor’s favor |
| Sharp pain once limits are hit | Pricing jumps feel more extractive than supportive |
| Complex pricing structures | Hard to predict bills and compare plans |
| Weak options for smaller builders | Indie 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 type | Meaning |
|---|---|
| Evaluations | Runtime feature flag checks |
| Tracked Events | Exposure, conversion, and related analytics events |
The current ladder looks like this:
| Plan | Price | Evaluations | Tracked Events | Projects | Environments | Seats |
|---|---|---|---|---|---|---|
| Free | $0 | 75k / month | 10k / month | 1 | 1 | 1 |
| Indie | $9 / month | 1M / month | 50k / month | 3 | 3 | 1 |
| Starter | $19 / month | 5M / month | 250k / month | Unlimited | 3 | 5 |
| Growth | $49 / month | 20M / month | 1M / month | Unlimited | 3 | 15 |
| Enterprise | From $799 / month | Custom | Custom | Custom | Custom | Custom |
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:
| Scenario | Result |
|---|---|
| Indie customer hits Starter-level usage | Total bill lands around $20 |
| Starter customer hits Growth-level usage | Total 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.
| Tier | Main identity | Key upgrade drivers |
|---|---|---|
| Free | sandbox / hobby | basic entry point |
| Indie | solo production | more projects, more environments, more real usage |
| Starter | small team production | seats, scheduled rollouts, webhooks, service accounts |
| Growth | mature team workflows | approvals, ownership, notifications, longer retention |
| Enterprise | governance and custom needs | security, 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:
| Area | Status |
|---|---|
| Product concept | very real |
| Core architecture | decided |
| Pricing model | defined |
| MVP feature set | essentially complete |
| TypeScript SDK | first pass done |
| Internal alpha | next |
| Additional SDKs | post-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.