Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions app-guides/multiple-processes.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@
sitemap: true
toc: true
nav: firecracker
author: thomas

Check warning on line 7 in app-guides/multiple-processes.html.md

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'thomas' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'thomas' a typo?", "location": {"path": "app-guides/multiple-processes.html.md", "range": {"start": {"line": 7, "column": 9}}}, "severity": "INFO"}
categories:
- guide
date: 2020-07-20
date: 2026-04-28
---

<div class="callout">
This guide discusses different ways to run multiple processes in your app. To learn about process groups in Fly Apps and the `[processes]` configuration in `fly.toml`, see [Run multiple process groups in an app](/docs/apps/processes/). For process group configuration with the Machines API, see the `config.processes` object in the [Machine config](docs/machines/api/machines-resource/#machine-config-object-properties).

Check failure on line 14 in app-guides/multiple-processes.html.md

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Vale.Terms] Use 'APIs?\b' instead of 'api'. Raw Output: {"message": "[Vale.Terms] Use 'APIs?\\b' instead of 'api'.", "location": {"path": "app-guides/multiple-processes.html.md", "range": {"start": {"line": 14, "column": 364}}}, "severity": "ERROR"}
</div>

This comes up a lot: how can you run multiple programs in an app on Fly.io? Recall that Fly.io apps are shipped to us in OCI images, usually built by Docker, and Docker has… opinions… about running multiple things in a container.

Well, [we don't use Docker to run images](https://fly.io/blog/docker-without-docker/). Your app is running in a [Machine](/docs/machines/), a fast-launching VM with its own kernel. You can do pretty much anything you want inside of it, including running as many programs as you like. Most of the time, the trick is just telling Docker how to do that.

There are a couple different ways to run multiple processes in a Fly.io app. All of them address the first rule of programs running in a Fly Machine: when your entrypoint program exits, our `init` kills the Machine and we start a new one. So at the end of the day, *something* has to keep running "in the foreground".
There are a couple different ways to run multiple processes in a Fly.io app. All of them address the first rule of programs running in a Fly Machine: when your entrypoint program exits, our `init` kills the Machine and we start a new one. So ultimately, *something* has to keep running "in the foreground".

### Setting the scene

Expand Down Expand Up @@ -129,9 +129,9 @@

(It's a contrived example, so I'm only lighting one of the ports up, but whatever).

### Use Supervisord

Check warning on line 132 in app-guides/multiple-processes.html.md

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'Supervisord' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'Supervisord' a typo?", "location": {"path": "app-guides/multiple-processes.html.md", "range": {"start": {"line": 132, "column": 9}}}, "severity": "INFO"}

The other Docker documentation suggestion: use `supervisor`. `supervisor` is an actual process manager; it'll run in the foreground and manage all our processes and, most importantly, when our processes exit, `supervisor` will (configurably) restart it.

Check warning on line 134 in app-guides/multiple-processes.html.md

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'configurably' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'configurably' a typo?", "location": {"path": "app-guides/multiple-processes.html.md", "range": {"start": {"line": 134, "column": 229}}}, "severity": "INFO"}

`supervisor` has [a lot of configuration options](http://supervisord.org/configuration.html+external). But because we're running on Fly.io, we mostly don't care about them; the platform is doing a lot of this work for us. So the `supervisor` configuration we want is pretty simple:

Expand Down Expand Up @@ -183,7 +183,7 @@
bar: /app/server -bar
```

A Procfile manager I like a lot is [overmind](https://github.com/DarthSim/overmind+external). `overmind` is a Go program, so it's got a small runtime, and you could, if you were fussy, build a container that just takes the `overmind` binary and none of its build deps. We won't bother, though, since we're already bringing those deps in. So:

Check warning on line 186 in app-guides/multiple-processes.html.md

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'deps' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'deps' a typo?", "location": {"path": "app-guides/multiple-processes.html.md", "range": {"start": {"line": 186, "column": 330}}}, "severity": "INFO"}

Check warning on line 186 in app-guides/multiple-processes.html.md

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'deps' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'deps' a typo?", "location": {"path": "app-guides/multiple-processes.html.md", "range": {"start": {"line": 186, "column": 264}}}, "severity": "INFO"}

Check warning on line 186 in app-guides/multiple-processes.html.md

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'overmind' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'overmind' a typo?", "location": {"path": "app-guides/multiple-processes.html.md", "range": {"start": {"line": 186, "column": 37}}}, "severity": "INFO"}

```Dockerfile
FROM golang
Expand Down Expand Up @@ -213,7 +213,7 @@

### There are so many other process managers

Use whichever you like! The only limitation you're going to run into is that Fly.io owns your `init` (sorry!); we have to be PID 1. There are a bunch of process managers that want to replace `init`, and those'll be tricky to get to work in a Fly.io app.

Check warning on line 216 in app-guides/multiple-processes.html.md

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'those'll' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'those'll' a typo?", "location": {"path": "app-guides/multiple-processes.html.md", "range": {"start": {"line": 216, "column": 204}}}, "severity": "INFO"}

### Maybe you want multiple apps, though

Expand All @@ -223,11 +223,27 @@

Fly.io apps can talk to each other over a [private network](https://fly.io/docs/networking/private-networking/) that's always available. They can find each other under the `.internal` top-level domain (if your apps are `foo` and `bar`, they'll be in the DNS as `foo.internal` and `bar.internal`). Because the network connection is private and encrypted, you can generally just talk back and forth without extra authentication until you know you need it; in other words, you can keep things simple.

The main conveniences you give up when splitting into separate apps are that secrets are shared across all process groups in a single app, and all process groups deploy from the same Docker image. There are also cases where separate apps are the only option. For instance, the [metrics-based autoscaler](/docs/launch/autoscale-by-metric/) operates on a whole app, so workloads that need independent scaling behavior have to live in their own apps.

You can still share a single built image across several apps. Build it once without deploying:

```cmd
fly deploy --build-only --push
```

This outputs a tag of the form `registry.fly.io/app:deployment-xxxx`. Any app in the same organization can then deploy from that image:

```cmd
fly deploy --image registry.fly.io/app:deployment-xxxx
```

The main thing to watch out for is that secrets have to be set on each app individually, which can mean some duplication.

### Maybe you don't need multiple processes

There are a bunch of reasons people want to run multiple things in a container that Fly.io already takes care of for you. For instance: [metrics are a built-in feature of the platform](https://fly.io/blog/hooking-up-fly-metrics/), as are logs. You might not need to run helper processes for this kind of stuff.

Another thing people run multiple programs to get is static asset HTTP service; you'll run your app server, and a small webserver alongside it to serve assets. You don't need to do this if you don't want! Instead, you can ask the Fly.io platform to do it for you, by adding `statics` directives to your `fly.toml`:

Check warning on line 246 in app-guides/multiple-processes.html.md

View workflow job for this annotation

GitHub Actions / Vale linter

[vale] reported by reviewdog 🐶 [Fly.Spelling] Is 'webserver' a typo? Raw Output: {"message": "[Fly.Spelling] Is 'webserver' a typo?", "location": {"path": "app-guides/multiple-processes.html.md", "range": {"start": {"line": 246, "column": 121}}}, "severity": "INFO"}

```toml
[[statics]]
Expand Down
Loading