The go-to resource for upgrading Ruby, Rails, and your dependencies.

Setting Up Foreman and Procfile.dev for Rails and Vite


Learn how to manage multiple development processes in a modern Ruby on Rails application with Vite for frontend tooling using Foreman and a Procfile.dev.

The Challenge of Modern Frontend Tooling in Rails

The classic Unix philosophy emphasizes building tools that do one thing and do it well. For a long time, though, Ruby on Rails local development took a different approach entirely: a single process — the Rails server — handled everything from receiving web requests to compiling JavaScript and CSS via Sprockets. It was the software equivalent of a one-person band.

This monolithic approach was convenient for getting started. However, as frontend tooling became more complex, that single process became overwhelmed. Modern Rails applications frequently leverage Vite — via the vite_ruby gem — to manage complex frontend assets, bringing significantly faster build times and Hot Module Replacement (HMR).

This architectural shift introduces a logistical challenge for developers. To achieve HMR and fast compilation, Vite runs its own dedicated development server (typically on port 3036), completely separate from the Puma web server running the Rails application (typically on port 3000).

Consequently, developers must remember to start two separate processes in two separate terminal tabs every time they begin working. We can solve this friction by using a process manager.

Evaluating the Options

There are three major approaches to managing these multiple processes in development. Depending on the particular circumstances you find yourself in, one of them may be more useful than the other two.

The first is the classic Foreman gem, which we will focus on in this article; this is the most ubiquitous tool to adopt, and it is the standard tool that Rails itself has historically adopted for its bin/dev scripts.

The second is Overmind. Overmind is heavily inspired by Foreman but runs processes in a tmux session. This allows you to attach to individual processes — for example, if you need to drop into a binding.irb session or a debugger within your Rails application.

The third option is Hivemind, which is positioned as a dependency-free alternative to Foreman written in Go.

Generally speaking, Foreman is the most straightforward to start with. The second option, though, will often make more sense if your team relies heavily on interactive terminal debuggers like pry or irb during the normal boot process, as Foreman aggregates standard input and output across all processes.

Introducing Foreman and the Procfile

Foreman is a process manager for Ruby applications, originally created by David Dollar. It reads a configuration file called a Procfile, which declares the various processes your application needs to run.

While a standard Procfile is often used to define production processes — such as web servers and background job processors like Sidekiq — we typically use a specialized file named Procfile.dev strictly for our local development environment.

Using Foreman to manage your local development environment ensures that your entire stack boots with a single command, reducing the cognitive load on your engineering team and ensuring consistent development environments.

Installing Foreman

First, we need to add Foreman to our system. Although you could add it to your Gemfile, Foreman is generally installed as a system-wide or global gem. This prevents version conflicts and keeps your application dependencies strictly focused on production requirements.

Run the following command in your terminal:

$ gem install foreman

Creating the Procfile.dev

Next, we will create our Procfile.dev file in the root directory of our Rails application. This file will define the two commands necessary to boot our application.

Create a file named Procfile.dev and add the following lines:

web: bin/rails server -p 3000
vite: bin/vite dev

We can notice a few things about this configuration. First, we explicitly define the port for the Rails server. Second, we assign clear, descriptive names (web and vite) to each process. Foreman will use these names to prefix the log output in your terminal, making it straightforward to distinguish between Rails application logs and Vite compilation logs.

You might also notice that we are not using bundle exec in our commands. This is because the Rails binstubs in the bin/ directory automatically handle the Bundler environment for us.

Running the Stack

With our configuration in place, we can boot both servers using a single command. In its most basic form, you can run foreman start without any arguments. This, however, will look for a file named Procfile — so we must pass the -f flag to specify our development configuration:

$ foreman start -f Procfile.dev

When you run this command, Foreman will start both the Puma server and the Vite development server. The output from both processes will be interleaved in your terminal, color-coded, and prefixed with the process name:

14:23:45 web.1  | started with pid 12345
14:23:45 vite.1 | started with pid 12346
14:23:46 vite.1 | Vite is running...
14:23:47 web.1  | * Listening on http://127.0.0.1:3000
...snip...

When you are finished working, pressing Ctrl+C will cleanly shut down both processes.

Of course, typing foreman start -f Procfile.dev every time you want to work on your application can be cumbersome. Rails conventions suggest we use a wrapper script in our bin/ directory.

Create a file named bin/dev:

#!/usr/bin/env bash
if ! gem list -i "^foreman$" -v ">= 0.87.0" > /dev/null 2>&1;
then
    echo "Installing foreman..."
    gem install foreman
fi

exec foreman start -f Procfile.dev "$@"

Make the script executable:

$ chmod +x bin/dev

This wrapper script checks if Foreman is installed, installs it if necessary, and then boots your Procfile.dev. Now, your team can start the entire application stack by running bin/dev.

Conclusion

Moving to Vite brings significant frontend performance benefits, but it requires adjusting our local development habits. By implementing Foreman and a Procfile.dev, we encapsulate the complexity of booting multiple servers into a single, reliable command. This small infrastructure investment ensures that your team can focus on writing code rather than managing terminal windows.

Sponsored by Durable Programming

Need help maintaining or upgrading your Ruby on Rails application? Durable Programming specializes in keeping Rails apps secure, performant, and up-to-date.

Hire Durable Programming