Procfile guide: syntax, process types, and running it locally

A Procfile is a plain text file named Procfile in the root of your project. Each line names a process and gives the command that starts it, written as name: command. Heroku defined the format. Local runners such as Foreman, Honcho, Overmind, and Rig read the same file, as does the Heroku CLI, so one list of commands can start a web server, a worker, and a scheduler together. This guide covers the syntax, what the special names mean, a complete file for a three-process app, how each runner treats it, and the mistakes that make a line quietly disappear.

Updated 8 min read

What a Procfile is

A Procfile declares the processes that make up an app. It does not install dependencies, build assets, or choose a language runtime. It only says what to run.

Heroku reads the file to decide what each dyno runs. On your own machine, a Procfile runner reads the same file and starts each command as a process. The format is a convention, not a standard. Heroku defines it, and every other tool decides what to accept, so check the manual of the runner you use. The name rules below are one example: Heroku lists hyphens in a process type, and Foreman’s manual does not. The Procfile glossary entry has the short definition.

Syntax

Each line has one shape:

Text
<process type>: <command>

The rules that matter in practice:

  • File name. Heroku requires the file to be named exactly Procfile, with no extension, in the root directory of the app. Its article says Procfile.txt is not valid. Rig also looks only for Procfile in the project root, so a name such as Procfile.dev is not read.
  • One process per line. A line is a process type, a colon, and a command. Write the command as you would type it in a shell.
  • Process type names. Heroku lists alphanumerics, hyphens, and underscores. Rig accepts letters, digits, hyphens, and underscores. Foreman’s manual lists letters, numbers, and the underscore only, so use underscores if you want to stay within what it documents.
  • Comments. Rig skips blank lines and lines that start with #. Check your own runner’s manual before you rely on comments there, and keep notes in a README if the file also deploys to Heroku.
  • Long commands. Rig does not support continuation lines, so each command stays on one line. Move a long command into a script file and call that.

Process types: web, worker, and release

The name before the colon is a label, and only two labels carry meaning on Heroku.

Process typeWhat it means on HerokuWhat to know locally
webThe only type that receives HTTP traffic from Heroku’s routers. Its command must bind to the port in PORT.Nothing on your machine routes traffic by process type, so any process can serve HTTP. The name does not choose its port.
workerNo special meaning. The usual name for background jobs, such as a queue consumer.An ordinary process. Name it for what it does.
releaseRuns in the release phase, before a new release is deployed. If it fails, the release is not deployed.heroku local does not run it, so run migrations yourself when you work locally.
Anything elseA free label, such as scheduler or clock.An ordinary process.

Write a Procfile for web, worker, and scheduler

Take a Node app with an HTTP server, a queue worker, and a scheduler that adds recurring jobs to the queue. The three entry points are src/web.js, src/worker.js, and src/scheduler.js. The Procfile is three lines:

Text
web: node src/web.js
worker: node src/worker.js
scheduler: node src/scheduler.js

The web process reads its port from the environment and falls back to a default, so it works under a runner that sets PORT and when you start it by hand:

JavaScript
const http = require("node:http");

const port = Number(process.env.PORT) || 3000;
http
  .createServer((req, res) => res.end("ok"))
  .listen(port, () => console.log(`web listening on ${port}`));

Four choices keep a file like this from causing trouble later:

  1. One program per line. Keep installs, builds, and migrations out of the Procfile. A web line that runs npm install && node src/web.js reinstalls on every start.
  2. Run one scheduler. A simple scheduler like this one enqueues each recurring job once per copy, so two copies enqueue every job twice. Locally you run one of each process type. If you deploy the Procfile to a platform that can run several copies of a type, keep the scheduler at one.
  3. Keep the scheduler out of the worker. A slow job then cannot delay the next scheduled run.
  4. Add release only when you need it. A line such as release: node scripts/migrate.js runs on Heroku before a deploy, and heroku local does not run it.

Paste the file into the Procfile validator to see how each line is read. It will note that the web command does not mention $PORT, which is fine here because the code reads process.env.PORT.

Environment variables and PORT

On Heroku, the web process has to bind to the port in PORT. On your machine nothing sets it unless the runner does or you do. Foreman sets it for each process: the value starts at the base port given with -p and rises by 100 for each process line. Rig exports PORT when a port is set for the project. Two habits keep one Procfile working in both places.

  • Read PORT with a fallback, as in the example above.
  • Do not hard-code a port in the command. web: node src/web.js --port 3000 pins every checkout of the app to port 3000, so two copies cannot run side by side.

Keep secrets and per-machine settings out of the Procfile. Foreman and Honcho both take -e to name an environment file, and Rig takes environment variables from the project’s active env profile.

Run it locally

Each runner starts from the same file:

Terminal
# Heroku CLI
heroku local

# Foreman
foreman start

# Honcho (Python)
honcho start

# Overmind (runs each process in tmux)
overmind start
  • Heroku CLI. heroku local starts the process types in your Procfile, and heroku local web starts one. It does not run the release type.
  • Foreman. foreman start runs one instance of each process type, foreman start web runs only that type, and foreman start -f Procfile.dev reads a differently named file.
  • Honcho. A Python port of Foreman. honcho start runs the file, and honcho -f Procfile.dev start reads another one. Its documentation says it is not meant to match Foreman feature for feature, so check the flags you rely on.
  • Overmind. Runs each process in its own tmux window, so tmux has to be installed. overmind connect worker attaches to that process, and overmind restart worker restarts it without touching the others. By default one process dying stops the rest, and -r restarts the processes you name.

A Procfile only describes processes. Whether a crashed process comes back, and whether one crash stops the rest, is the runner’s decision. Test it once: kill the worker and watch what happens to the web process. For a wider comparison with tmux, concurrently, and Docker Compose, read run multiple dev servers locally.

Common mistakes

  • Wrong file name. Procfile.dev and Procfile.txt are not Procfile. Rig does not read them. Foreman and Honcho can read another name through -f, but Heroku requires Procfile.
  • A space before the colon. web : node src/web.js does not match Rig’s pattern, because the name must be followed directly by the colon. Rig does not list that line as a script.
  • A dot or space in the name. mailer.preview fails the same pattern, and it is outside the characters Heroku lists. Use mailer-preview, or mailer_preview if you use Foreman.
  • A port hard-coded in web. The command ignores the PORT that the runner or platform sets.
  • Setup work in the command. Installs and builds belong in a setup step, not in a line that runs on every start.
  • Expecting release to run locally. heroku local skips it, so a migration that works on Heroku may never have run on your machine.

What Rig does with a Procfile

Rig reads a Procfile in the project root. This is everything it does with the file:

  • It looks for a file called Procfile in the project root. Names such as Procfile.dev are not read.
  • It accepts a line only when it matches ^([A-Za-z0-9_-]+):\s*(.+)$. It skips blank lines and lines that start with #, and it has no continuation lines.
  • It turns each process type into a script you can select. It marks a script as recommended when it looks like a server.
  • It runs the command with /bin/sh -c, or with cmd.exe /d /s /c on Windows.
  • When a port is set for the project, it appends --port N to the command and exports PORT, VITE_PORT, HOST_PORT, and npm_config_port.
  • It takes environment variables from the project’s active env profile.
  • It lets extra scripts run alongside the selected one.

For the example file, Rig lists web, worker, and scheduler as three scripts. With port 4000 set on the project and web selected, Rig runs node src/web.js --port 4000 with PORT=4000 in the environment. The server above reads PORT, so the extra argument is ignored.

The flag goes on the end of the line

Rig appends --port N to the whole command line, and a command that does not accept --port still receives it. In a chain such as npm run build && node src/web.js, the flag attaches to the last command only. Keep a Procfile command to one program, or put the program that should receive the flag last.

One selected script, plus extras

Rig treats each process type as a script you select, and runs extra scripts alongside the selected one. Foreman’s foreman start runs one instance of every process type in one command, so check how your project is set up before you assume all three processes start together. See Procfile projects for the settings, and Procfile plus sidecars for how a Procfile and sidecar processes sit on one board.

Frequently asked questions

What is a Procfile?

A plain text file named Procfile that lists an app’s processes, one per line, as a process type, a colon, and a command. Heroku uses it to decide what each dyno runs. Runners such as Foreman, Honcho, Overmind, and Rig read the same format to start the processes on your machine.

Does a Procfile need a web process?

Only if the app serves HTTP traffic on Heroku. The web type is the only one that receives traffic from Heroku’s routers, and its command must bind to the port in PORT. A process that receives no HTTP traffic can use any other name.

How do I run a Procfile locally?

Use a Procfile runner. heroku local runs the file through the Heroku CLI, foreman start and honcho start use Foreman and Honcho, and overmind start runs each process in its own tmux window. Rig lists each process type as a script you can start from the app.

What does the release process type do, and does it run locally?

On Heroku, the release command runs in the release phase, before a new release is deployed, and a failure stops the release. heroku local does not run it. Run your migration command by hand, or from another script, when you work locally.

Can I name the file something other than Procfile?

Heroku requires the exact name Procfile. Foreman and Honcho accept another file name through -f. Rig looks for a file called Procfile in the project root, so a file such as Procfile.dev is not picked up.

How does Rig run a Procfile?

Rig turns each process type into a selectable script and runs the command with /bin/sh -c, or with cmd.exe on Windows. If the project has a port set, it appends --port N to the command and exports PORT, VITE_PORT, HOST_PORT, and npm_config_port.

Sources

  1. Heroku Dev Center: The ProcfileOfficial documentation, checked 13 October 2026
  2. Heroku Dev Center: Release PhaseOfficial documentation, checked 13 October 2026
  3. Heroku Dev Center: Running Apps LocallyOfficial documentation, checked 13 October 2026
  4. Heroku Changelog: Heroku local no longer runs the release process typeOfficial documentation, checked 13 October 2026
  5. foreman(1): manage Procfile-based applicationsOfficial documentation, checked 13 October 2026
  6. Honcho: manage Procfile-based applicationsOfficial documentation, checked 13 October 2026
  7. Honcho: Using ProcfilesOfficial documentation, checked 13 October 2026
  8. Overmind: process manager for Procfile-based applications and tmuxOfficial documentation, checked 13 October 2026
  9. Overmind source: start/command.go, tmux checkOfficial documentation, checked 13 October 2026
  10. Rig documentation: Procfile projects (parser and runner behaviour confirmed in Rig’s source code)Rig source code, checked 13 October 2026

Run your whole stack from one window

Rig is a Mac app that starts, stops, and watches the processes in your project, with logs and ports in one place. Local use is free, and your source code stays on your Mac.

Related

https://userig.app/learn/procfile-guide