PM2 — Using Bun to Start Your App

We migrated the code running the superchargejs.com website from CommonJS to ESM. We used ts-node in combination with SWC to run the CommonJS TypeScript code. But ts-node isn’t working with TypeScript and ESM (there’s an open issue).

Now that ts-node isn’t working, we need to use a different tool. Bun is a new JavaScript runtime with built-in TypeScript support. The Supercharge website code is small, a good fit to test a new runtime like Bun.

We’re deploying the project using PM2 and this tutorial shows you how to configure PM2 to start the process using the Bun runtime.

PM2 Series Overview

PM2 Configuration to Run Your App with Bun

PM2 is a daemon process manager that keeps your application running continuously. You can configure the way PM2 should run your application using flags on the command line or a configuration file. We recommend the configuration file to surface the way you start your app.

PM2 uses Node.js as the default interpreter for the script that you want to start. You can change to a different interpreter, like Bun, Ruby, Python, and any other if needed.

Here’s a sample PM2 configuration file using Bun to run your application:

module.exports = {  
  name: 'superchargejs.com',

  script: 'server.ts',
  interpreter: 'bun',
}

If your system user doesn’t have the global bun command available in your terminal, you can define a path to Bun’s installation and PM2 will resolve that for you:

module.exports = {  
  name: 'superchargejs.com',

  script: 'server.ts',
  interpreter: '~/.bun/bin/bun',

  // or use an absolute path
  // interpreter: '/home/marcus/.bun/bin/bun'
}

PM2 Cluster Mode is not Supported With Bun

Running apps in PM2 cluster mode is connected to Node.js as the interpreter. PM2 uses Node.js’ cluster module to scale your clustered application. Using a different interpreter than Node.js forces your app to start in PM2 fork mode.

If you would add the exec_mode: 'cluster' and instances: 2 options in the Bun PM2 configuration file, it would still start as a single instance in fork mode:

module.exports = {  
  name: 'superchargejs.com',

  script: 'server.ts',
  interpreter: 'bun',

  /**
   * cluster mode is not working when using a custom "interpreter"
   * @see https://github.com/Unitech/pm2/issues/1575
   */
  exec_mode: 'cluster',
  instances: 2,
}

Starting your configuration file with PM2 results in a single, forked process:

launch@supercharge-001-fra1:~$ pm2 ls  
┌─────┬──────────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id  │ name                 │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├─────┼──────────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 1   │ superchargejs.com    │ default     │ N/A     │ fork    │ 12345    │ 1m     │ 1    │ online    │ 0%       │ 80.2mb   │ marcus   │ disabled │
└─────┴──────────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘

Enjoy running your Bun applications with PM2!


Mentioned Resources

Explore the Library

Find interesting tutorials and solutions for your problems.