Skip to content
MethodInsights

Feature flags for a small team — without the platform theatre

Shipping without downtime starts with a kill switch you will actually turn off.

A feature flag is a runtime decision. Not a dashboard subscription, and not an env var you forget to turn off.

12 min read
Stylised process diagram with checks and gates — feature flags as gates in the rollout, not a platform dashboard.

Method & rollout

If you are searching for feature flags in Next.js or a rollout without downtime, you are usually here: something has to go to production, and you do not dare show it to everyone. Someone suggests LaunchDarkly. Someone sets NEXT_PUBLIC_NEW_CHECKOUT=true and calls it a flag. Someone merges behind a branch that never merges because 'we are waiting for go-live'.

The CI/CD post is about the preview URL before merge. This one is about what happens after merge — when the code is in production and you still want to decide who sees it. A flag is not a product. It is a runtime read with an owner and a kill date. Without those two things you have a settings panel you never clean up.

TL;DR

The main points

  • A flag is a decision you can change without rebuilding. If it needs a rebuild, it is configuration — not a flag.
  • Preview deploys answer 'may this merge?'. Flags answer 'may this tenant see it now?'.
  • A small team dies of flag graveyards, not of missing an enterprise platform.
  • Start with a boolean and a kill switch. Targeting and percentages come when you have a sentence about who turns it off.
  • In Next.js the usual lie is a NEXT_PUBLIC_ flag that already sits in the bundle before you 'turn it off'.
  • Every flag has an owner and a delete date. Otherwise it has become the product.

Why this matters at all

A rollout without downtime is not a load-balancer trick. It is that you can ship code that is dark for most people, and turn it on when you dare — or off when it burns. Without that valve you merge at night, hotfix in a panic, or let a feature rot on a branch because 'we cannot roll out in parts'.

Small teams buy the wrong medicine. They see a slide with percentage rollouts, multivariate tests and 'governance', and draw a platform project on top of a checkout that only needed to be switchable. Or they do the opposite: they have no valve, so every release is a jump. Both cost weeks. One in theatre. The other in rollback.

It is also a product question, not only a DevOps question. A flag that lives for a year is a hidden setting. Two truths in the code. Two paths in QA. Two ways a customer can hit a bug. Preview deploys catch what you can see before merge. They do not catch the flag you forgot to delete after go-live.

We write this because 'feature flags' has become a purchase you make before you have a sentence about what gets turned on. An honest setup is boring: a boolean, a place you can read it in the request, a person who owns it, and a date when the code has only one path. Without that sentence you have a dashboard. You do not have a rollout you can defend.

What a feature flag actually is — and what it is not

A feature flag is a value runtime reads while the request runs. The code is already out. The decision is not. That is the difference between deploying and turning on. If you have to rebuild the image, touch a Vercel env and wait for a new deploy, you have configuration. That can be right — a kill switch you rarely touch. It is not a flag you can use in the middle of an incident.

That is why NEXT_PUBLIC_ENABLE_BILLING=true is almost always a lie when someone says flag. NEXT_PUBLIC_ lands in the browser bundle. The client already has the answer before your 'off' exists. Middleware that reads a server secret or a row in your database can still say no. A client bundle cannot take back a no you shipped two deploys ago.

A flag is also not a settings product. 'Every tenant can turn on dark theme, the new dashboard and beta invoices' is feature-toggle as a business. That needs UI, audit, support. Fine when that is the product. Poison when you started with 'just so we can roll out quietly' and ended with an internal control panel nobody dares touch.

And it is not a substitute for preview. A PR without a URL is still a review in the blind. The flag does not help you see the layout before merge. It helps you have the code out without every customer standing on the new path. If you only have one of those, you only have half the rollout.

What typically goes wrong in a small team

The first failure is buying the platform before you have one boolean you actually turn on and off. You get an SDK, an audit log and 'environments', and then you use one flag for checkout. Three months later the SDK is the only reason the flag still exists, and nobody remembers the API key. You pay for governance you do not read.

The second failure is env-var theatre. You change a value, trigger a redeploy, and call it 'rollout without downtime'. That is a slow kill switch. It is better than nothing if you only have one button you touch in an incident. It is useless if you want to turn something on for one tenant this afternoon without rebuilding.

The third failure is targeting as the first feature. 'Ten percent of sessions, except staff, plus this workspace'. Now you have a rules language. Now two flags can interact. Now a customer can see A on desktop and B on phone because the cookie did not follow. Targeting is right when you have a question targeting answers. It is wrong as the default on an MVP.

The fourth failure is letting the flag become how you store disagreement. Product wants it out. Support does not. You merge and leave the flag off. Half a year later nobody dares delete the code because 'we might need it'. That is not a rollout. That is a disagreement you pushed into runtime.

Preview deploy vs. feature flag — two different valves

Preview deploy

The answer before merge: can we see it, and dare we take it in?

  • A URL per pull request, close to production
  • Catches layout, copy and the bugs the diff hides
  • Stakeholders can say yes without running it locally
  • When you merge, the code is out for everyone — unless you also have a flag

Feature flag

The answer after merge: who sees it, and can we turn it off now?

  • The code is in production; the visibility is not
  • A kill switch you can flip in the middle of an incident
  • One tenant, one workspace, or 'only us'
  • Needs a delete date, or it becomes a second codebase

How a small team starts — without buying a control tower

Without this order you get either theatre or no valve at all.

  1. 01

    Write what the flag turns on — in one sentence

    Not 'the new dashboard'. 'Checkout v2 for internal users, so we can take an order without touching the old cart'. If you cannot say that, you are not ready for a flag. You are ready for a branch or a no.

  2. 02

    Pick one boolean, read on the server

    A row in your database, an edge config you actually understand, or a small Unleash/Flagsmith you host yourself. Read it in the request that decides. Not in a client bundle. Not in a NEXT_PUBLIC_ you hope to take back.

  3. 03

    Give it an owner and a delete date

    Owner is a name, not 'the team'. The date is the day the code has only one branch — flag gone, old path gone. Set the date when you create it. Move it on purpose. Do not let it expire in silence.

  4. 04

    Practise off before you practise on

    The danger is not turning it on. It is that you have never turned it off in the middle of something. Take an afternoon: turn it on for yourselves, turn it off, check that the old path still works. If off needs a deploy, you do not have an incident valve.

  5. 05

    Say no to the second flag until the first is dead

    Two living flags are the start of a matrix problem. A small team can carry one rollout valve at a time. If you need three, you need a clean-up week — not a new SDK.

A rollout without downtime is not a platform purchase. It is that you can turn off what you just turned on — without rebuilding.

Next.js — the same duty, special places you fool yourselves

The App Router makes it easy to believe 'it runs on the server'. A Server Component can read a flag correctly. A Client Component that gets the flag as a prop you cached too hard, or that fetches a NEXT_PUBLIC_ itself, can show the wrong world for minutes. Cache is part of the flag. If you cannot say how long an 'off' is allowed to be wrong, you do not have a kill switch. You have a hope.

Middleware is an honest place to gate a whole path — /new-checkout only when the flag is on. It is also a place you can make the request slow, or cache the decision so hard that off does not land. Keep the flag read short. Keep it close to what you actually want to hide. Do not gate the whole site because one flow must be switchable.

Vercel Flags, edge config and the usual SaaS SDKs can be right when you have several environments, several teams and a need to flip without a deploy. They are wrong as the first commit on an MVP where one person can update a row and refresh. Buy the pipe when the read has become a product. Do not buy it because a blog post said feature flags are 'modern'.

If you are considering changing host or framework 'to get flags', be honest: you change the place, the decision can still sit. A Next.js site with the same env theatre is not a new valve. Change stack if you also have other reasons. Do not change because a slide said edge makes rollout invisible. Rollout is who sees the code. Not where it compiles.

What you should typically do in the situation you are in

The left is what you typically say. The right is the next step we typically recommend.

  • Situation

    We dare not merge because it must be switchable in production

    Next step

    Merge behind one server boolean with an owner and a delete date. Preview is already yes/no on the URL — the flag is yes/no after merge

  • Situation

    We set a NEXT_PUBLIC_ flag and call it a rollout without downtime

    Next step

    Move the read to the server. What the browser already got, you cannot take back with an env change

  • Situation

    We want to roll out to ten percent and A/B the heading at the same time

    Next step

    You want two things. First a kill switch. Targeting and experiments are another product — and another mess if you mix them

  • Situation

    We are looking at LaunchDarkly before we have turned one flag off in an incident

    Next step

    Practise off on one boolean you own. Buy the platform when several teams need to flip without touching your database

  • Situation

    We have seven flags, and nobody remembers what is true in production

    Next step

    Clean-up week. Delete or merge each branch. No new flags until the list is short enough to fit on one card

Checklist before you call it feature flags

If you are missing several of these, the sentence is a slide — not a valve.

  • The read happens in the request, not in a client bundle you already sent
  • Off works without a new image — you have tried it, not only on
  • Every flag has a name, an owner and a delete date you dare move in public
  • Preview deploys still exist; the flag does not replace them
  • You have at most a few living flags, and you can say what production shows without opening a dashboard
  • No 'settings for every tenant' hidden as rollout flags

Questions we get again and again

  • Does a small team need feature flags at all?

    You need a valve when the code must go out before you dare show it to everyone — one tenant, an internal workspace, a kill switch in the middle of an incident. You do not need a flag platform because a slide said 'modern delivery'. Many small teams are fine with preview deploys and a rare env change. Take the flag when 'off now' is a real requirement. Do not take it because you want to sound like a platform team.

  • Isn't a Vercel env var enough?

    It is enough as a rare kill switch if you accept a redeploy. It is not enough if you want to turn something on for one customer this afternoon, or off in the middle of a fault without waiting for a build. And a NEXT_PUBLIC_ var is almost never enough: it sits in the bundle. Say 'configuration we touch in incidents'. Do not say feature flag unless runtime can read a no without you rebuilding.

  • When is LaunchDarkly or Unleash the right call?

    When several people need to flip without touching your database, when you have several environments that must mirror each other, or when audit is a real requirement — not a nice-to-have on a slide. Unleash you host yourself can be the right middle. A full SaaS platform is right when flag reads have become operations for several teams. It is wrong as the first dependency on a checkout one developer owns.

  • Can we use flags for A/B tests and targeting right away?

    You can. You should not, until you have one boolean you dare turn off. A/B is an experiment with statistics and an expiry date. Targeting is a rules language. Feature rollout is a valve. Mix them, and you cannot say whether a bug sat in the variant, in the rule or in the product. One job per flag. One flag per rollout. Experiments in a tool you can turn off without touching the rollout.

  • How long may a flag live?

    Short enough that you can still remember the old branch. A rollout over days or a few weeks is a flag. Half a year is a hidden setting. If the date moves a third time, it is not a rollout. It is disagreement or a settings product. Merge the branch, delete the flag, or admit you have built two products and need to design that honestly — with UI, support and a real setting, not a runtime hack.

If you only dare merge when everyone must see it at once

Let us separate preview, valve and platform.

A boolean you can turn off beats a dashboard you buy before you have practised a no.

Why we wrote this

This is how we think — and it's what we build.

Our insights are about the work we actually do. If this hit something you're working on, there's a concrete service that lines up.