Shibumi Shibumi - 18 days ago 5
Node.js Question

Is it possible to deploy a Node.js application to Heroku without a web dyno?

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 running
npm 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 the
web
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!

Answer

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.

Comments