# A new deployment strategy beyond bluegreen

**URL:** <https://community.fly.io/t/a-new-deployment-strategy-beyond-bluegreen/28132>\
**Category:** General\
**Tags:** wishlist\
**Created:** [June 19, 2026, 2:26pm UTC](https://community.fly.io/t/a-new-deployment-strategy-beyond-bluegreen/28132 "2026-06-19T14:26:36Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![fabrizio](https://avatars.discourse-cdn.com/v4/letter/f/8dc957/32.png) [@fabrizio](https://community.fly.io/u/fabrizio)\
**Post date:** [June 19, 2026, 2:26pm UTC](https://community.fly.io/t/a-new-deployment-strategy-beyond-bluegreen/28132/1 "2026-06-19T14:26:36Z")

</div>

I use bluegreen deployment strategy to deploy my app. It works as intended but I really have the need of a slightly different strategy that serve well especially in the context of TCP connections. The idea is the following:

- green machines are created
- green machine health checks are awaited
- blue machines are kept running until they have any active connection (can also be based on soft\_limit)
- blue machines do not accept any new connection, only green machines (from the moment the are ready)
- blue machines are destroyed only when there’s no more active connections to them

In essence is very similar to bluegreen but less destructive. This way we need less logic in our app to handle deployment because there’s always a version of the app running as soon as it is used.

What do you think?

---

<div class="post-metadata">

**Author:** ![fabrizio](https://avatars.discourse-cdn.com/v4/letter/f/8dc957/32.png) [@fabrizio](https://community.fly.io/u/fabrizio)\
**Post date:** [June 19, 2026, 2:28pm UTC](https://community.fly.io/t/a-new-deployment-strategy-beyond-bluegreen/28132/2 "2026-06-19T14:28:33Z")

</div>

It would also help in case of multiple services in a monorepo, because a consistent version of them all is running at the same time

---

<div class="post-metadata">

**Author:** ![lubien](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/lubien/32/41919_2.png) [@lubien](https://community.fly.io/u/lubien)\
**Post date:** [June 19, 2026, 3:34pm UTC](https://community.fly.io/t/a-new-deployment-strategy-beyond-bluegreen/28132/4 "2026-06-19T15:34:41Z")

</div>

This sounds like a very interesting use case! I have multiple angles on how to answer that

> Prior context:
> 
> - `cordon` means "make this machine not routable for folks anymore, just keep whoever is still connected to it.
> - cordoned machines wont get new connections BUT will keep existing ones alive.

## Option A) Bluegreen already does that

This scenario is something bluegreen already seems to solve, you might just need to tweak a couple things.

When green machines are started and have passing health checks we uncordon them (so they are reachable via proxy) and then **we cordon the blue machines**.

Bluegreen waits for blue machines to stop after it sends SIGINT (can be configured, see `fly deploy --help` and look for `--singal`). If you want to change how long to wait for blue machines to stop look for `--wait-timeout`.

If your app can gracefully terminate after all connections are closed then you’re golden! No new connections will be handled after

> Note: check if your CI does not have a maximum timeout that would suddenly stop everything!

## Option B) If you still want a custom workflow

Assuming increasing the timeouts is not the fix for your use case.

What `fly deploy` currently does is essentially calls to machines API to create/update machines.

May I suggest that you orchestrate this custom deployment logic either via machines API via your framework of choice or just by using `flyctl` commands?

Here’s how I’d do it myself (disclaimer: I used an agent to generate these commands and did not try it myself, I recommend trying in a test app)

```auto
# Step 1: Build only, capture image ref
fly deploy --build-only --push 2>&1 | grep "^image:" 
# → image: registry.fly.io/my-app:deployment-01234567

# Step 2: List existing machine IDs
fly machine list -q
# → <id1> <id2> <id3>

# Step 3: Deploy new machines, excluding all existing ones
# --ha=false prevents spawning extra standby machines per group
fly deploy --image registry.fly.io/my-app:deployment-01234567 \
  --exclude-machines <id1>,<id2>,<id3> \
  --ha=false

# Step 4: (after verifying new machines are healthy) Cordon the old ones
fly machine cordon <id1> <id2> <id3>

```

The decision on how to make them get destroyed when they’re not serving traffic anymore. One trick you can use for each machine that needs to be destroyed:

```auto
fly machine update <machine_id> \
  --autostop stop \
  --machine-config '{"auto_destroy": true}'

```

Let the proxy stop it after its idle and the machine also destroys itself instead of staying there forever 🙂

I want to reiterate that I asked an agent to generate those commands as I did not have time to try it myself! (But Im a human and I read your question and suggested things according to how I’d have done myself)

## C) Make an agent orchestrate your deployment

I still think that Option A is the way to go but…

`flyctl launch` is just a fancy open source client for [https://api.machines.dev/](https://api.machines.dev/)

Copy your question and my reply into an agent and ask it to generate a custom shell script to orchestrate your deployments with all your details! Im not joking, it works surprisingly well

Here’s `flyctl` source: [GitHub - superfly/flyctl: Command line tools for fly.io services · GitHub](https://github.com/superfly/flyctl)

* * *

Let me know if this helps!

---

<div class="post-metadata">

**Author:** ![fabrizio](https://avatars.discourse-cdn.com/v4/letter/f/8dc957/32.png) [@fabrizio](https://community.fly.io/u/fabrizio)\
**Post date:** [June 21, 2026, 7:40pm UTC](https://community.fly.io/t/a-new-deployment-strategy-beyond-bluegreen/28132/5 "2026-06-21T19:40:40Z")

</div>

Hello, thanks for replying.

So, option A is not an option for my use case, I cannot rely simply on wait\_timeout. But I get that it is an option for other users and if they step into this post they should take it in consideration.

But you’re definitely right, there cannot be a valid deployment strategy for everybody and writing our own script is the solution. For example your option B is already a good strategy for me, I just have to investigate better on using the machine API.

I let you know if I’m able to create something meaningful and maybe share it with the community.

---

<div class="post-metadata">

**Author:** ![halfer](https://avatars.discourse-cdn.com/v4/letter/h/df705f/32.png) [@halfer](https://community.fly.io/u/halfer)\
**Post date:** [June 21, 2026, 10:08pm UTC](https://community.fly.io/t/a-new-deployment-strategy-beyond-bluegreen/28132/6 "2026-06-21T22:08:16Z")

</div>

My own addition to this topic is not to struggle with Bash. It simply isn’t sufficient as a fully-fledged scripting language for the task - eventually you’ll need JSON decoding, conditionals, loops etc. I recommend that folks use what they normally use on the application side - Ruby, Java, Python, PHP, etc.

Once you’ve got some simple cURL primitives working, and some error handlers to catch common failure cases, you can start using it like Lego. I’d also not be surprised if the major library providers (NPM, Packagist, etc) already have a Fly API library you can use out of the box.

---

<div class="post-metadata">

**Author:** ![fabrizio](https://avatars.discourse-cdn.com/v4/letter/f/8dc957/32.png) [@fabrizio](https://community.fly.io/u/fabrizio)\
**Post date:** [June 22, 2026, 1:37pm UTC](https://community.fly.io/t/a-new-deployment-strategy-beyond-bluegreen/28132/7 "2026-06-22T13:37:16Z")

</div>

One problem I have with this solution is that machine update api will reboot the machine and this is exactly what should be prevented. Any hint on how to change the stop strategy of a machine without restarting it? Is it possible? Is there any alternative?

---

<div class="post-metadata">

**Author:** ![lubien](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/lubien/32/41919_2.png) [@lubien](https://community.fly.io/u/lubien)\
**Post date:** [June 22, 2026, 1:58pm UTC](https://community.fly.io/t/a-new-deployment-strategy-beyond-bluegreen/28132/8 "2026-06-22T13:58:50Z")

</div>

I do have some ideas but first Id like to check with you when that’s needed.

- Are you talking about blue machines?
- Can you confirm at which point it is needed for those to not be rebooted by proxy? (I assume it is after green machines are uncordoned and blue machines are cordoned)

---

<div class="post-metadata">

**Author:** ![fabrizio](https://avatars.discourse-cdn.com/v4/letter/f/8dc957/32.png) [@fabrizio](https://community.fly.io/u/fabrizio)\
**Post date:** [June 22, 2026, 2:02pm UTC](https://community.fly.io/t/a-new-deployment-strategy-beyond-bluegreen/28132/9 "2026-06-22T14:02:55Z")

</div>

Yeah, sorry, I’ve been not very precise. After the green machines are marked as healthy, we cordon the blue machines and we update their configuration. At this point, due to calling machine update, the blue machines reboot. This is what should be avoided.

---

<div class="post-metadata">

**Author:** ![lubien](https://sea1.discourse-cdn.com/fly1/user_avatar/community.fly.io/lubien/32/41919_2.png) [@lubien](https://community.fly.io/u/lubien)\
**Post date:** [June 22, 2026, 2:16pm UTC](https://community.fly.io/t/a-new-deployment-strategy-beyond-bluegreen/28132/10 "2026-06-22T14:16:45Z")

</div>

Thanks for the confirmation.

If you mean the update call itself is rebooting the machine I think we have an option to make the machine keep stopped if it was previously stopped which is skip\_launch I think but…

If the blue machine is stopped then you can just delete it right? That means the started blue machines are what’s left.

They:

- Might be serving connections or not
- Need to be destroyed when they become idle
- Proxy will stop them when they become idle
- New connections won’t happen because they’re cordoned.

The easiest way I can think to tackle this would be to have something in the background that destroy those when they stop. Here’s a brainstorm of different ways to handle that scenario

- If you have some kind of orchestrator somewhere that can run regular jobs you could use it to watch for when these stop and then remove them. Heck, I bet even GitHub actions can do that.
- If you want to put something under your own app code you could create a secret endpoint that schedules a “destroy myself” function when your machine stops by the proxy (remember that the proxy stops machines with that signal I mentioned above, you can trap that to trigger the function)
- You could use machine metadata API to update the machine without a reboot and then in your app read that metadata and then destroy the running machine when it stops.
- Leave old machines cordoned and make the CI clean then on the next deploy or on the next run or using a cron job

I think I’m missing some obvious things, don’t take that list as the only ways you can do this!

I’m happy to continue rubber ducking this with you

---

<div class="post-metadata">

**Author:** ![fabrizio](https://avatars.discourse-cdn.com/v4/letter/f/8dc957/32.png) [@fabrizio](https://community.fly.io/u/fabrizio)\
**Post date:** [June 24, 2026, 10:04am UTC](https://community.fly.io/t/a-new-deployment-strategy-beyond-bluegreen/28132/11 "2026-06-24T10:04:31Z")

</div>

This is exactly what I’m going to do, destroy a machine that is cordoned at some point, either marking it with metadata or by checking if it’s cordoned or checking if it’s running an old version of the app.

The ideal would be to have a way to change machine configuration without rebooting it, but I see why that may not be possible.

---

<div class="post-metadata">

**Author:** ![system](https://global.discourse-cdn.com/fly1/original/3X/6/e/6e8955d00cb218e186ebbe3a6ab06fefdce15290.svg) [@system](https://community.fly.io/u/system)\
**Post date:** [July 4, 2026, 10:05am UTC](https://community.fly.io/t/a-new-deployment-strategy-beyond-bluegreen/28132/12 "2026-07-04T10:05:05Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
