Node.js buildpack

Deploy a Node.js app in India

Connect a GitHub repository that has a package.json and the Node.js buildpack builds and starts it: no Dockerfile to write, no server to patch. An Express API, a plain Node server or a compiled TypeScript backend all go live the same way, with PostgreSQL in the plan and HTTPS on your own domain.

From ₹100/month + 18% GST, PostgreSQL included, billed in INR.

Deploy Node.js in 5 steps

  1. Connect your GitHub repository

    Create an app in the dashboard, connect GitHub and choose the repository and branch to deploy. Not on GitHub? Create a deploy token for the app and upload a tar.gz of the project with curl, from your laptop or from CI.

  2. Let the Node.js buildpack detect it

    A package.json at the repository root selects the Node.js buildpack. It installs the Node version named in engines.node, installs your dependencies, runs your build script when there is one, and starts the web line of your Procfile, or npm start when you have no Procfile.

  3. Add your environment variables

    Put API keys, session secrets and third-party credentials in the app's environment variables in the dashboard, not in the repository. They are encrypted at rest, and changing one restarts the app without a rebuild. PORT is already set for you; read it with process.env.PORT.

  4. Attach PostgreSQL and read DATABASE_URL

    Add a PostgreSQL 16 database to the app in one click and its connection string appears in the environment as DATABASE_URL. node-postgres takes it as connectionString; Prisma reads it from env("DATABASE_URL") in schema.prisma; Knex and Sequelize accept the same URL.

    const { Pool } = require('pg');
    const pool = new Pool({ connectionString: process.env.DATABASE_URL });
  5. Point your domain at the app

    Your Node.js app answers on its free HTTPS address as soon as the first deploy finishes. Add your own domain, publish the TXT record the dashboard shows to prove it is yours, then an A record for the root domain or a CNAME for www; the certificate is issued without any setup in your code.

A minimal Node.js app that deploys

Procfile
web: node server.js
package.json
{
  "name": "my-api",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.21.0"
  },
  "engines": {
    "node": "22.x"
  }
}
server.js
const express = require('express');
const app = express();

app.get('/', (req, res) => res.json({ ok: true }));

// The platform sets PORT; never hard-code 3000.
app.listen(process.env.PORT || 5000);

Node.js gotchas to know before you push

  • Listen on process.env.PORT, not 3000

    Traffic reaches your container on the port in PORT. An app that hard-codes 3000 or 8080 builds without complaint, but nothing listens where the router sends requests, so visitors get a 502 instead of your app.

  • devDependencies are gone at runtime

    After the build script runs, the buildpack prunes devDependencies. Compile TypeScript or bundle in the build script, and keep anything that runs in production, such as your ORM client, in dependencies.

  • Only /app/data survives a redeploy

    Each deploy starts from a fresh build, so uploads written next to your code disappear. Write user uploads and anything else you must keep under /app/data, the persistent volume every app gets, or keep it in PostgreSQL.

  • Run migrations as a release step

    Add a release line to the Procfile, for example release: npx prisma migrate deploy or release: npx knex migrate:latest. It runs once per deploy before the new version takes traffic, so schema and code change together.

FAQ

Node.js hosting questions

The range you give in engines.node in package.json, such as "22.x". Without it the buildpack uses its own default, which moves when the buildpack is updated, so pin the major version you test on.
No. With no Procfile the app is started with npm start. Add one when you want a different start command, a release step for migrations, or a second process type such as worker: node worker.js.
Yes, as long as the compile step lives in the build script (tsc, nest build) and the start command runs the compiled JavaScript with node. TypeScript itself can stay in devDependencies because nothing needs it once the build has finished.
Declare it as a worker in the Procfile, for example worker: node jobs.js, then give it an instance on the app's Scale page: every process type except web starts at zero. It runs in its own process beside the web process, and web and worker scale separately, up to 10 instances each within your plan's memory.
Prefer an app? Add this site to your home screen.Get the app
Deploy a Node.js App in India – PaaS from ₹100/mo | Domain India