Dark Launches and Soft Rollouts: Ship the Code Before You Ship the Feature

A dark launch ships a feature to production with nobody seeing it; a soft rollout then reveals it to a few users at a time. How to run both safely with feature flags.

  • dark-launch
  • deployments
  • rollouts

The safest release is one where the risky part already happened days ago, quietly, while nobody was looking. That is the idea behind a dark launch: put the new code in production, run it against real traffic, and keep it invisible until you have proof it works. The reveal, when it comes, is a configuration change, not a deploy.

A dark launch answers one question (“does this code survive production?”) and a soft rollout answers the next one (“is this feature right for users?”). They are different techniques for different risks, they happen in that order, and feature flags are what make both of them cheap. This guide covers what each one is, when to reach for it, and how to run the pair without leaving a mess behind.

Key Takeaways

  • A dark launch deploys a feature to production turned off or invisible, so the code runs under real conditions before any user sees it. Facebook coined the practice in 2008 by load-testing Chat from real browsers with no UI drawn (Meta Engineering).
  • A soft rollout is the next step: reveal the feature to a small slice of users, watch, then widen. Dark launch lands the code; soft rollout decides who sees it and when.
  • The two manage different risks. Dark launch targets infrastructure and correctness risk at 0% exposure. Soft rollout targets feature and product risk at 1% exposure and up.
  • Feature flags are the control plane for both: ship at off, validate, ramp by percentage, and reverse with a one-click kill switch instead of a redeploy.
  • The one rule that ties them together: a launch flag is a temporary flag. Remove it once the feature is fully live, or it becomes flag debt.

How to use this guide. This is the practical how-to for the two techniques and the order you run them in. For the one-paragraph definitions, see the dark launch glossary entry and the percentage rollout entry. For the wider strategy these two sit inside, read the two-pillar progressive delivery playbook. For the failure mode they replace, see the big-bang release in feature flag anti-patterns.


1. What a dark launch actually is

A dark launch deploys a feature into production without releasing it to users. The code is live, running or ready to run behind a flag held at 0%, but no one can see it. You validate it under real production conditions first, then make it visible when you decide. The point is to separate two events that a normal release fuses together: shipping the code, and turning it on.

That separation is the whole value. When deploy and release are the same moment, every deploy is an act of faith. You find out whether the new code holds up at the worst possible time, with 100% of users already on it. A dark launch moves the discovery earlier and shrinks the audience for it to zero. If the new service buckles under load, the only witnesses are your dashboards.

The canonical example is also the origin of the term. When Facebook built Chat in 2008, they could not safely guess whether their backend would survive tens of millions of concurrent users. So before any chat box appeared, “Facebook pages would make connections to the chat servers, query for presence information and simulate message sends without a single UI element drawn on the page” (Meta Engineering). Real browsers generated real load against the real backend, invisibly. Dark-launch testing ran from February 2008; the first visible message went out in April, by which point the scaling questions were already answered. The release itself was almost boring, which is exactly the goal.


2. The two flavours of dark launch

“Dark launch” covers two related techniques, and it helps to name them, because they validate different things.

A back-end dark launch exercises a new code path without surfacing its results. You run shadow traffic against the new service, dual-write to the new data store, or compute a value and throw it away, purely to see how the system behaves under production load and against production data. This is the Facebook Chat pattern. It tests capacity, latency, and correctness before a single user depends on the answer.

A hidden-feature dark launch deploys the finished user-facing feature behind a flag held at off, then flips it on later. Nothing about the new UI is exposed; the code simply waits in production. This is less about load and more about decoupling the deploy schedule from the release decision, so a feature can ship on a Tuesday and launch on a Thursday with no second deploy in between.

Both rely on the same property: the code reaching production is one decision, and the feature becoming visible is a separate one. Feature flags give you that separation directly. The branch lives behind a named flag, the deploy carries it to production dormant, and exposure becomes a value you edit rather than a release you cut.


3. Dark launch vs soft rollout vs canary vs A/B test

These four terms get used as if they were interchangeable. They are not, and choosing well starts with knowing which question each one answers.

A dark launch asks: does this code work in production at all? Exposure is 0%. A soft rollout (often called a soft launch) asks: is this feature good for users? Exposure starts small and grows. A canary release asks: is this new version of the service healthy? It routes a small slice of traffic to the new build and promotes or aborts based on error rates. An A/B test asks: which variant performs better on a metric? It splits users into groups and measures the difference.

The cleanest way to keep them straight is by what each one exposes at its first step.

What each technique exposes at step one A horizontal bar chart comparing how much is exposed to users at the first step of four techniques. A dark launch exposes zero percent, with no UI drawn. A canary exposes about five percent of traffic. A soft rollout exposes one to five percent of users. A big-bang release exposes one hundred percent at once. The point is that the first three start small or invisible, while big-bang does not. Share exposed at the first step (smaller is safer) Dark launch 0%: code runs, no UI exposed Canary ~5% of traffic, gated on error rate Soft rollout 1–5% of users, ramped over days Big-bang 100% at once: everyone, immediately
Three of these limit the blast radius at step one; the big-bang release is the pattern the other three exist to avoid.

In practice you combine them. A team dark-launches a new pricing service to prove it under load, then puts the user-facing change behind a soft rollout once the backend is trusted, and may run an A/B test on the variant during the ramp. The techniques compose because they manage different risks at different layers.


4. How to dark launch with feature flags

The mechanics are simpler than the theory. Wrap the new path in a flag, ship it at off, and choose what “on” means for your validation.

For a hidden-feature dark launch, the code is just a branch behind a named decision:

// The flag is held at off in production. The code is live but invisible.
if (client.boolVariation('checkout-v3', user, false)) {
renderCheckoutV3();
} else {
renderCheckoutV2();
}

The deploy carries checkout-v3 to production with every user resolving to false. Nothing changes for anyone. When you are ready to validate against real people, you turn it on for a cohort you control: internal staff and dogfooding accounts first, via a targeting rule rather than a percentage. That is still a dark launch in spirit, because the public sees nothing, but now your own team is exercising the real feature in the real environment.

For a back-end dark launch, “on” means run the new path and discard the result. You call the new service, compare its output to the old one or simply measure its latency and error rate, and serve the old result to the user regardless. The flag controls whether the shadow path executes, so you can ramp the synthetic load up and down by editing config, exactly as Facebook ramped its invisible Chat traffic.

Either way, the rollback story is the same and it is the reason flags fit this job. If the dark-launched code misbehaves, you set the flag back to off. There is no rebuild, no redeploy, and no waiting. With Featureflip, that change streams to every connected SDK in sub-second, and evaluation happens in-process, so holding a feature dark costs you nothing on the hot path.


5. The soft rollout: turning the dark launch up slowly

Once the code has proven it survives production, the dark launch is done and the soft rollout begins. This is where you stop asking “does it work?” and start asking “is it good?” You reveal the feature to a small, growing share of real users and watch the metrics that tell you whether to keep going.

A soft rollout is a percentage rollout with discipline attached. You move the flag from 0% to 1%, then 5%, then 25%, then 100%, pausing at each step long enough to read the signal. The exposure curve looks like a staircase, and the flat segment before it (the dark launch) is the part most write-ups skip.

From deploy to general availability A line chart of the share of users who can see a feature over its lifecycle. After deploy, the line stays flat at zero percent through the dark launch window, when the code runs invisibly. It then ramps up through the soft rollout in steps, one percent, five percent, twenty-five percent, and on to one hundred percent at general availability. The flat zero-percent segment is the dark launch; the rising staircase is the soft rollout. Share of users who can see the feature, over time 0% 25% 50% 75% 100% Deploy Dark launch (invisible) Soft rollout GA: 100%
The shaded window is the dark launch: code in production, zero users exposed. The staircase that follows is the soft rollout, each step a config change you can pause or reverse.

Two details separate a soft rollout from just yanking a slider. First, the bucketing has to be sticky: a user who lands in the 5% should stay in it as you widen, not flicker in and out on every evaluation. Featureflip’s rollout strategies hash on a stable user key so assignment is deterministic and consistent across every replica and SDK. Second, each step is gated on a metric, not a timer. You widen because error rates held and the business number looked right, not because an hour passed. If a step looks wrong, you do not roll forward; you flip back to the previous percentage, and because that is a config push, recovery is immediate.


6. When to reach for which

The decision is about the risk you are actually carrying, not about which technique sounds most thorough.

You are worried about…Reach forExposure at step one
New service surviving production loadBack-end dark launch0% (shadow traffic)
Decoupling a deploy from its launch dateHidden-feature dark launch0% (flag held off)
A new feature being wrong for usersSoft rollout1–5% of users
A new build or version being unhealthyCanary releasesmall traffic slice
Which of two variants performs betterA/B testsplit cohorts

Most genuinely risky launches use the first and third together: dark launch to retire the infrastructure risk, then soft rollout to retire the product risk. The mistake is skipping straight to a wide release because the staging environment looked fine. Staging is not production, and the gap between them is precisely the gap a dark launch is built to close. The pattern these techniques exist to retire is the big-bang release: ship to everyone at once and hope.


7. The pitfalls that bite

The techniques are simple; the ways they go wrong are predictable. Four are worth naming.

Leaving the flag in. A launch flag is a temporary flag. Once the feature has been at 100% for a release cycle or two, the flag is dead weight, and dead flags accumulate into the kind of inventory that carries a real maintenance cost (Martin Fowler). Schedule its removal at the same time you create it. The mechanics of doing that without breaking anything live in the feature flag cleanup playbook.

Treating a dark launch as a substitute for testing. Running code invisibly in production validates load, latency, and integration with real data. It does not validate that the feature is correct. Unit tests, integration tests, and review still do their jobs; a dark launch is the layer you add on top for the questions only production can answer.

Dual-write divergence. A back-end dark launch that dual-writes to a new store can silently drift from the old one. If you are running both paths, compare their outputs and alert on the difference, rather than assuming the new path agrees just because it did not error.

Soft rollout without sticky bucketing. If assignment is not deterministic, a user can see the new feature on one request and the old one on the next. That is worse than a clean rollout, because it looks like a bug to the user and to your support team. Make sure the rollout hashes on a stable key before you widen past internal staff.

Get those four right and the pair becomes routine. The broader discipline of rolling out well, across all of it, is covered rule by rule in feature flag best practices, and the deeper reason this all works, separating the act of deploying from the act of releasing, is the same boundary explored in feature flags vs environment variables.


The shorter version

A dark launch deploys a feature to production while keeping it invisible, so the code runs under real load and against real data before any user depends on it. Facebook gave the technique its name in 2008 by load-testing Chat from real browsers with no UI drawn. A soft rollout is the next step: once the code is proven, you reveal the feature to a small, growing share of users, pausing at each percentage to read the metrics before you widen. The two manage different risks in order, infrastructure and correctness first at 0% exposure, then product fit from 1% upward, and feature flags are what make both cheap, because shipping dark, ramping by percentage, and rolling back are all configuration changes rather than deploys. Run a back-end dark launch when you are worried about load, a hidden-feature dark launch when you want to separate the deploy from the launch date, and a soft rollout when the feature itself might be wrong for users. Keep the bucketing sticky, gate each step on a metric instead of a timer, and remove the flag once the feature is fully live so today’s launch does not become next quarter’s debt.


Frequently asked questions

What is a dark launch?

A dark launch deploys a feature into production without releasing it to users. The code is live, running or held behind a flag at 0%, but invisible. You validate it under real production conditions first, then make it visible when you choose. Facebook popularised the practice in 2008 by load-testing Chat from real browsers before any chat UI appeared (Meta Engineering).

What is the difference between a dark launch and a soft rollout?

A dark launch is about deploying without releasing: getting code safely into production while it stays invisible, to test load and correctness. A soft rollout is about how you then reveal it, expanding from a small cohort of users to everyone. They compose in that order: dark launch to land the code, then soft rollout to ramp exposure. A dark launch sits at 0% exposure; a soft rollout starts around 1–5% and grows.

Is a dark launch the same as a canary release?

No. A canary release routes a small slice of live traffic to a new build and promotes or aborts based on its health, so users in the canary do see the change. A dark launch exposes nothing to users; the code runs invisibly to test the system itself. A canary asks whether a new version is healthy; a dark launch asks whether the code survives production at all.

How do feature flags enable dark launches and soft rollouts?

Feature flags decouple deploy from release. You ship the code behind a flag held at off (the dark launch), then turn exposure into a value you edit: a targeting rule for internal staff, then a percentage rollout you ramp from 1% to 100% (the soft rollout). Rollback is a one-click config push rather than a redeploy, which is what makes both techniques safe to use routinely.

When should I use a dark launch?

Use a back-end dark launch when you are unsure a new service or code path will hold up under production load or against production data, the case Facebook Chat faced. Use a hidden-feature dark launch when you want to separate a deploy from its launch date, shipping the code early and flipping it on later. In both cases the goal is to retire infrastructure and correctness risk before any user is exposed.


Featureflip gives you the control plane for dark launches and soft rollouts: ship a feature behind a flag held at off, validate it against internal cohorts with targeting rules, ramp exposure with sticky percentage rollouts, and reverse any of it with a kill switch that streams to every connected SDK in sub-second, all as configuration rather than a deploy. If you want to run the dark-launch-then-soft-rollout loop on your own features, start with the free Solo plan.