Runway
Runway is built and operated in the EU!

Multi-process

First steps

This example builds a small Node.js app with three processes: a web server, a background worker, and an init script that runs once per deploy. For the concepts shared by every language, see the multi-process guide.

Setup the project

$ mkdir my-app && cd my-app
$ npm init -y
$ npm install express
$ echo "node_modules" > .gitignore

The web process

server.js
const express = require('express')

const app = express()
const port = process.env.PORT || 3000

app.get('/', (req, res) => {
  res.send('Hello from the web process!')
})

app.listen(port, () => {
  console.log(`web listening on ${port}`)
})

The init process

init runs once before the web process starts, on every deploy. It is the place for database migrations: if it exits non-zero, the deploy fails and the previous version keeps serving.

migrate.js
// Replace this with your migration tool, e.g. `knex migrate:latest`,
// `prisma migrate deploy`, `node-pg-migrate up`, ...
console.log('running migrations...')
console.log('migrations done')

The worker process

worker runs continuously and does not listen on a port. It can reach the web process over the loopback interface on PORT. Keep it running: if it exits, the whole app restarts.

worker.js
const port = process.env.PORT || 3000

let running = true
process.on('SIGTERM', () => { running = false })

async function tick() {
  // do a unit of background work here, e.g. pull a job off a queue
  const res = await fetch(`http://localhost:${port}/`)
  console.log('worker checked web:', res.status)
}

async function main() {
  while (running) {
    await tick()
    await new Promise((r) => setTimeout(r, 5000))
  }
  console.log('worker shutting down')
}

main()

Wire it together

Set the start script so the app still works without a Procfile and for local development:

$ npm pkg set scripts.start="node server.js"

Then add a Procfile. Because a Procfile replaces the default process list entirely, the web: line has to be declared explicitly alongside init and worker:

Procfile
web: node server.js
init: node migrate.js
worker: node worker.js

Create the app and configure it:

$ runway app create
$ runway app config set PORT=3000
$ git add -A && git commit -m "initial commit"

Deploy to Runway

runway app deploy

Run runway app open to see it live, or check the Runway UI. Check runway app logs if something’s off.

Check that all processes are running:

$ runway app ps

Next steps