For some backstory and reference, here are some quotes from a few Heroku documentation pages.
From the Heroku Node.js Support > Activation:
The Heroku Node.js buildpack is employed when the application has a
package.json
file in the root directory.
From Heroku Node.js Support > Default web process type:
First, Heroku looks for a Procfile specifying your process types.
If no
Procfile
is present in the root directory of your app during the build process, your web process will be started by runningnpm start
, [...]
From Process Types and the Procfile > Process types as templates:
A Procfile contains a number of process type declarations, each on a new line. Each process type is a declaration of a command that is executed when a dyno of that process type is started.
For example, if a
web
process type is declared, then when a dyno of this type is started, the command associated with theweb
process type, will be executed. This could mean starting a web server, for example.
I have a package.json
file in the root (which will activate the Node.js buildpack), and I've also included a Procfile
in the root with the following contents:
service: npm start
I would assume that not defining a web
dyno would cause it to not be created; only the service
dyno should be created, following the configuration declared in the Procfile
.
Instead, what happened is that an active web
dyno was automatically created using npm start
and an inactive service
dyno was created using the definition in Procfile
. I then had to:
heroku ps:scale web=0
heroku ps:scale service=1
I can definitely imagine wanting to run a Node.js "service" application on Heroku that does not accept any incoming connections, only making outgoing ones. Is there a way to configure the Node.js buildpack to not automatically create a web
dyno when one is not defined? I've looked through lots of documentation looking for a way to either: (1) define it as such or (2) remove the automatically generated web
dyno; but, I haven't found anything.
Thanks for the help!
I ended up opening a helpdesk ticket with Heroku on this one. Got a response from them, so I'll post it here. Thanks Heroku support!
The short answer is that, no, currently you'll need to heroku scale web=0 service=1
in order to run a service without a public web
process. For a longer explanation:
Early on, the Node.js Buildpack checked for the presence of a Procfile
and, if missing, created a default one with web: npm start
. This made it easy to create apps without a web process, since you could just provide a Procfile
that defined some processes, omitting web
from the list.
However, as more and more users needed arrays of buildpacks instead of a single one, that solution created issues. Node is the most popular first buildpack, since it's frequently used by Java, Python, PHP, and Ruby apps to build front-end assets. Whenever an app without a Procfile
ran Node first, and another buildpack second, Node would inject its own default Procfile
(web: npm start
), and the second buildpack would then not create its default Procfile
as one already existed in the filesystem. So injecting a default Procfile when one is missing from the app creates problems downstream for multilingual apps.
So, we stopped creating a default Procfile and instead used default_process_types in bin/release. This fixes the issue of subsequent buildpacks inheriting incorrect default Procfiles, but since default_process_types
is extended rather than replaced by the Procfile
process list, apps without a web
process defined in their Procfile
will get the default web
process merged in. This is why web
appears even without a web
entry in Procfile
.
We also don't want to surprise any customers with unexpected bills. Some apps have many process types, some of which are only to be run occasionally, some limited to a single instance, some which need to be scaled up and down, etc, so defaulting everything to 1 rather than 0 could cause extra billing as well as app malfunctions. This is why non-web processes are scaled to zero by default.