FerryDocs
Guides

Scaling and limits

Run more instances of a service, set its memory and CPU limits, and see what Ferry does after a crash.

Edit on GitHub

A service runs 1 by default. Each instance can use 512 of memory and 1 CPU. Change these numbers with three commands:

Terminal
ferry scale api 3               # run 3 instances
ferry update api --memory 1G    # give 1 GiB of memory to each instance
ferry restart api               # apply the new limit

Ferry also repairs your app when it crashes or runs out of memory. This page tells what you see then, and what to do.

Run more instances

Terminal
ferry scale api 3
Scaled 'api' to 3 instance(s)

To set the number when you create the service, add --instances:

Terminal
ferry create api --repo https://github.com/you/api --instances 2

builds nothing and starts no new . Ferry starts the new instances from the . A new instance gets traffic when it accepts connections. When you scale down, Ferry stops the extra instances. Each one has 10 seconds to stop. There is no downtime.

ferry status shows each instance, with its CPU and memory:

Terminal
ferry status api
api: live — 3/3 instance(s) running
INSTANCE   DEPLOY     STATE     PORT    CPU            MEMORY                 RESTARTS   STARTED
6040c7     4a6f817d   running   63295   0.0% / 1 CPU   11.9 MiB / 512.0 MiB   0          16s ago
8cb56c     4a6f817d   running   63326   0.0% / 1 CPU   11.9 MiB / 512.0 MiB   0          6s ago
90f134     4a6f817d   running   63325   0.0% / 1 CPU   11.9 MiB / 512.0 MiB   0          6s ago
RuleValue
Number of instances1 to 50
Service types, , ,
No scalingA : each run has its own container. A service with a : 1 instance only.
AutoscalingNone. You choose the number.

How the instances share the work

The gives the requests of a web service or a static site to each instance in turn. This is . On the of its environment, the name of the service gives the addresses of all its instances. Each instance of a worker runs the same start command.

Two requests of one user can go to two different instances. Keep shared data, for example sessions, in a database and not in the memory of one instance.

Set memory and CPU limits

A is the most memory and CPU that one can use. Each instance and each job run of the service gets the limits of the service. Thus 3 instances can use 3 times the limit.

Terminal
ferry update api --memory 2G --cpu 0.5
ferry restart api --follow
Updated 'api'
Resource limits apply to the next deploy or restart: ferry restart api

ferry create and ferry up also accept --memory and --cpu. The value default goes back to the server default. ferry show api prints the limits of the service.

A new limit applies at the next deploy or . A restart uses the live image again and builds nothing. The deploy log shows the limits of the new instances:

==> Limits: 2 GiB memory, 1 CPU per instance

Write a size

LimitYou writeFerry readsRange
Memory512, 512M, 1G, 1.5GA number with no unit is MiB. G is GiB.16 MiB to 1 TiB
CPU0.5, 2, 500m500m is 500 millicores: half a core.0.01 to 512 CPUs

Limits of a datastore

A gets its new limits immediately, with no restart:

Terminal
ferry db update app-db --memory 2G --cpu 1

For a Redis datastore, Ferry sets the Redis maxmemory to 3/4 of the memory limit. When this part is full, Redis refuses new writes. See Databases.

Change the server defaults

A service or a datastore with no limit of its own gets the server defaults: 512 MiB and 1 CPU. To change them, start with these flags:

Terminal
ferryd --default-memory-limit 1G --default-cpu-limit 2

The value 0 removes the default limit. ferry info shows the defaults and the size of the server. See Server options.

On a server with 1 CPU, the default of 1 CPU is the full server. Use --default-cpu-limit 0.5 there.

What happens at a limit

LimitDefaultAt the limit
Memory512 MiBThe stops the process. This is an . Docker starts the container again.
CPU1 CPUThe kernel slows the container down. The app continues to run.
Processes and threads1024The container cannot start one more process. Change the value with ferryd --pids-limit.

A limit is a maximum, not a reservation. Ferry does not check that all the limits together fit on the server. A build has no limit. It can use all the memory and CPU of the server.

When an app crashes

Docker starts a crashed container again immediately. During that time, the proxy sends the requests to the other instances. If the container disappears, the starts a new instance in about 10 seconds. You do not have to do anything.

The RESTARTS column of ferry status counts the restarts of each instance. The state of the service is while it has fewer instances than you asked for.

A service with 1 instance

While Docker restarts the only instance, the proxy answers 503. For an important web service, run 2 instances or more.

Ferry tests the path only during a deploy. After that, the proxy only tests that the instance accepts connections. Thus an app that hangs with an open port continues to get requests. Make your app exit when it cannot serve. Then Docker starts it again.

When an app runs out of memory

ferry status marks an instance that the kernel stopped for memory. The last line tells you what to do:

api: degraded — 1/2 instance(s) running
INSTANCE   DEPLOY     STATE                                    PORT    CPU              MEMORY                  RESTARTS   STARTED
3f2a1c     7d0e52aa   running                                  63012   2.1% / 0.5 CPU   301.4 MiB / 512.0 MiB   0          12m ago
9b4e07     7d0e52aa   restarting (OOM killed, exit code 137)   -       -                -                       3          -
note: instance 9b4e07 was killed for running out of memory (limit 512 MiB). Raise the limit with 'ferry update api --memory <SIZE>', then 'ferry restart api'.

In the dashboard, the card of the instance on the Overview page shows an OOM killed badge. Its Raise the limit link opens Settings → Resources.

Give the service more memory, then restart it. Or find the memory leak in your app.

Terminal
ferry update api --memory 1G
ferry restart api

The result of an out-of-memory kill is different for each type of container:

ContainerResultMessage
Instance of a live serviceDocker starts it again.Server log: instance a1b2c3 of service 'api' ran out of memory (limit 512 MiB) — raise the service's memory limit
New instance in a deployThe deploy fails.instance ab12cd ran out of memory (limit 512 MiB) — raise the service's memory limit
Job runThe run fails.the job ran out of memory (limit 64 MiB) — raise the service's memory limit
DatastoreDocker starts it again.Server log: datastore 'app-db' ran out of memory (limit 1 GiB) — raise the datastore's memory limit

For a datastore, raise the limit with ferry db update NAME --memory SIZE. It needs no restart.

When the server restarts

If ferryd stops, Docker continues to run your containers. Services continue to reach their datastores on the private network. But no public traffic arrives, because the proxy is part of ferryd. Deploys stop. Cron jobs skip their runs, and Ferry does not run them later.

When ferryd starts again, it does these steps:

  1. It marks the interrupted deploys and job runs as failed, with the error interrupted by server restart.
  2. It installs the routes of each service. Then the proxy accepts connections.
  3. It starts the instances that are not there, and it restarts the datastores.

Ferry does not try an interrupted deploy again. Start it again yourself:

Terminal
ferry deploy api

To start ferryd again after a crash or a reboot, run it with systemd. See the Production checklist.

Common problems

ProblemFix
instances must be at least 1 (use suspend to stop a service)To stop all the instances, run ferry suspend api.
instances must be between 1 and 50Use 50 instances at most.
services with a disk are limited to 1 instanceTwo instances cannot write to one disk. A service with a disk runs 1 instance.
A new limit has no effectRun ferry restart api. A limit applies at the next deploy or restart.
New instances do not have your new variablesA scale uses the live deploy. Run ferry restart api.
An instance restarts again and again with OOM killedRaise the memory limit, then restart. Or fix the memory leak.
The app is slow, and the CPU column is at the limitRaise the limit with --cpu, then restart.
the CPU limit (8 CPUs) is more than the Docker host has: capped at 4 CPUsThe server has fewer CPUs than the limit. Ferry uses all the CPUs of the server. To remove the warning, set a lower --cpu.
After an upgrade of Ferry, an app or a database stops at 512 MiBOlder versions set no limit. Give it more memory with ferry update or ferry db update.
A deploy fails with not enough free disk spaceFerry needs 1 GiB free to build. Run docker image prune.

On this page