Configuration and fly.toml

All Fly applications have a fly.toml file which describes how the application should be configured when it is deployed onto the Fly platform. This configuration includes the application name, builder to be used (optional), ports, services and handlers to set up and parameters for health checks.

The file is in TOML format (github reference). If you are unfamiliar with TOML, here's a useful introduction. It is made up of lines with either key/value settings or sections (noted by values surrounded by one or more pairs of square brackets).

You don't need to create a fly.toml file by hand. Running flyctl apps create generates one for you.

Fly.toml - line by line

The app name

The first key/value in any fly.toml file is the application name. This will also be used to create the host name that the application will use by default. For example:

app = "restless-fire-6276"

Whenever flyctl is run, it will look for a fly.toml file in the current directory and use the application name in that file. This behavior can be overriden by using the -a flag to set the application name, or on some commands (such as deploy) by using a -c flag to point to a different fly.toml file.

The build section

The optional build section contains key/values concerned with how the application should be built. It is added at fly apps create time by using --builder buildername in the command line. An example build section could look like this:

  builder = "cloudfoundry/cnb:bionic"

Here the builder is being set to use the cloudfoundry cloud native buildpack for Ubuntu Bionic. To learn more about buildpacks and Fly, refer to this blog posting Simpler Fly deployments for NodeJS, Rails, Go, and Java.

Without a [build] section, flyctl will look for and use a Dockerfile in the directory as the packaging instructions when it comes to deploying the application.

The services section

The services section configures the mapping of ports on the application to ports and services on the Fly platform. These mappings determine how connections to the application will be handled on their journey from the Fly edge network to running Fly applications.

Services is a table of tables in TOML, so the section is delimited with double square brackets, like this:

  internal_port = 8080
  protocol = "tcp"
  • internal_port : The port the application will use to communicate with clients. Default is 8080. We recommend applications use the default.
  • protocol : The protocol that the application will use to communicate.


The services concurrency sub-section configures the applications behavior with regard to concurrent connections and compute scaling. It is a simple list of key/values, so the section is denoted with single square brackets like so:

    hard_limit = 25
    soft_limit = 20
  • hard_limit : When an application instance is at or over this number of concurrent connections, the system will bring up another instance.
  • soft_limit : When an application instance is at or over this number of concurrent connections, the system is likely bring up another instance.


For each external port you want to accept connections on, you will need a services.ports section. One for each port, the section is denoted by double square brackets like this:

    handlers = ["http"]
    port = "80"

This example defines a http handler on port 80.

  • handlers : An array of strings, each string selecting a handler process to terminate the connection with at the edge. Here, the "http" handler will accept HTTP traffic and pass it on to the internal port of the application which we defined earlier.
  • port : A string which selects which external ports you want Fly to accept traffic on. You can configure an application to listen for global traffic on ports 80, 443, 5000, and ports 10000 - 10100.

You can have more than one services.ports sections. The default configuration, for example, contains two. We've already seen one above. The second one defines an external port 443 for secure connections, using the "tls" handler.

    handlers = ["tls", "http"]
    port = "443"

The details of how these handlers manage network traffic, and other handlers available, are detailed in the Network Services documentation.


When a service is running, the Fly platform checks up on it by connecting to a port. The services.tcp_checks section defines parameters for those checks. For example, the default tcp_checks look like this:

    interval = 10000
    timeout = 2000
  • interval: The time in milliseconds between connectivity checks.
  • timeout: The maximum time a connection can take before being reported as failing its healthcheck.


Another way of checking a service is running is through HTTP checks as defined in the services.http_checks section. These checks are more thorough than tcp_checks as they require not just a connection but a successful HTTP status in response (i.e, 2xx). Here is an example of a services.http_checks section:

    interval = 10000
    method = "get"
    path = "/"
    protocol = "http"
    timeout = 2000
    tls_skip_verify = false

Roughly translated, this section says every ten seconds, perform a HTTP GET on the root path (e.g. looking for it to return a HTTP 200 status within two seconds. The parameters of a http_check are listed below.

  • interval: The time in milliseconds between connectivity checks.
  • method: The HTTP method to be used for the check.
  • path: The path of the URL to be requested.
  • protocol: The protocol to be used (http or https)
  • timeout: The maximum time a connection can take before being reported as failing its healthcheck.
  • tls_skip_verify: When true (and using HTTPS protocol) skip verifying the certificates sent by the server.
  • service.http_checks.headers: This is a sub-section of services.http_checks. It uses the key value pairs as a specification of header and header values that will get passed with the http_check call.

Note: The services.http_checks section is optional and not generated in the default fly.toml file.