Progress update on scaling a Rails Application

Demo time!

For the impatient, here is a slew of commands:

git clone https://github.com/rubys/rails-visitor-counter.git welcome
cd welcome
bundle add fly.io-rails
bundle update
bin/rails generate fly:app --anycable --redis --passenger --nats
bin/rails deploy
fly open

If you run this, it will deploy a simple visitor counter application. The count will start at two as the first access was made to verify that the application is alive. Nothing too fancy, but if you open a second browser window to the same URL, both windows will show the new count.

The complete instructions on how the application is built can be found in the readme: rails-visitor-counter/README.md at main · rubys/rails-visitor-counter · GitHub

Per the generate fly:app parameters, instead of Puma, Action Cable, and Upstart Redis, this application uses Phusion Passenger, AnyCable, and installs a local copy of Redis. It also installs nats, which I will get to in a minute. There are plenty of other parameters, such as name, org, and region; and serverless will scale to zero, and litefs, but those are the subjects of other demos.

Now for the best part

Use your favorite editor to edit fly.toml. Change the processes section to read:

[processes]
  app = "bin/rails fly:server[web=1;redis=0;anycable-rpc=1;anycable-go=0]"
  ws  = "bin/rails fly:server[web=0;redis=1;anycable-rpc=0;anycable-go=1]"

What this defines is that you want two machines, with the four applications split across the two machines. A 1 means that that application will run on that machine, and a 0 means that the app may be needed by the other machine. redis, for example, is used by the web application; and anycable_rpc is used by the anycable_go application. Technically web=0; can be omitted from the second list, but whatever.

To deploy, run:

bin/rails deploy

I was unable to get avahi working for service discovery, and even if I could I read that it may take five or more minutes for things to publish, so I wrote my own using nats. Its not robust, and only demo quality, but hopefully can be replaced in the future by some proper service discovery facility. It may add up to 30 seconds to the startup, and if you look at the logs you may see one of the anycable processes starting up before redis, complaining that redis is not available, but retrying shortly thereafter connecting.

Everything works using Private Networking · Fly Docs

Some assumptions I made: port 80 and 443 go to the first machine, as does the the volume necessary to support sqlite3. Realistically, the zeros and ones aren’t the ideal interface, and the developer will want to be able to control volume and machine sizes, may want to expose other ports, may want to have multiple regions with different configurations on different regions, etc. Ultimately, this is probably a Goldilocks problem - the process section in the toml file may be too lightweight, something like terraform may be too heavyweight, and some DSL might be able to strike the right balance.

3 Likes