pboss logo pboss.docs
Menu

More

Recipes

Copy-paste recipes for pboss — production APIs with clustering and health checks, watch mode, cron restarts, containers, deploys, and programmatic monitoring.

Short, copy-pasteable recipes for real situations. Each links to the full reference behind it.

Language quick starts#

# TypeScript server — runs on Bun, Deno, or Node (via tsx) per the chain
pboss start server.ts --name ts-api

# Node.js server, pinned
pboss start server.js --interpreter node --name node-api

# Deno server, pinned, with a scoped permission set
pboss start server.ts --interpreter "deno run --allow-net" --name deno-api

Production API with clustering and health checks#

pboss start server.ts \
  --name api \
  --instances max \
  --port 3000 \
  --max-memory-restart 512M \
  --health-check-url http://localhost:3000/health \
  --health-check-interval 15000 \
  --log-max-size 50M \
  --log-retain 10 \
  --log-compress

One command: every CPU core put to work, workers restarted if they bloat past 512MB, unhealthy workers recycled on failed probes, logs rotated at 50MB with 10 gzip-compressed generations. Background: cluster mode, health checks, log rotation.

Development mode with watch#

pboss start server.ts --name dev-api --watch --ignore-watch node_modules,.git,dist

Restart on save, with node_modules, .git, and build output excluded so a build doesn’t bounce your server. See watch options.

Scheduled restart (daily at 3 AM)#

pboss start server.ts --name api --cron "0 3 * * *"

For applications that benefit from regular recycling — leaking native buffers, long-lived connections — a standard cron expression restarts the process on schedule. See the --cron flag.

Multiple environments via ecosystem#

{
  "apps": [
    {
      "name": "api-staging",
      "script": "./server.ts",
      "env": { "NODE_ENV": "staging", "PORT": "3000" }
    },
    {
      "name": "api-production",
      "script": "./server.ts",
      "env": { "NODE_ENV": "production", "PORT": "8080" }
    }
  ]
}

One file, both environments, independently addressable: pboss restart api-staging. See ecosystem files.

Docker container (foreground mode)#

A Bun-based app, on the Bun image:

FROM oven/bun:latest
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun add -g pboss
CMD ["pboss", "start", "--no-daemon", "./server.ts"]

A Node.js app looks the same on the Node image — pboss installs and runs through whatever runtime the container already has:

FROM node:22-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm install -g pboss
CMD ["pboss", "start", "--no-daemon", "./server.js"]

--no-daemon keeps pboss as the foreground entrypoint so the container stays up. Compose, Kubernetes, and the --raw logging pattern are in Foreground mode & Docker.

Full production setup#

pboss start ecosystem.config.json
pboss save
pboss startup install
pboss dashboard
pboss list

Start the whole topology, persist it, install the boot service, and open the dashboard. After a reboot, systemd / launchd / Task Scheduler starts the daemon and your processes resurrect automatically. See Startup scripts.

Monitoring with Prometheus and Grafana#

pboss dashboard --metrics-port 9616
curl http://localhost:9616/metrics

Then add the target to your prometheus.yml and import the Grafana dashboard. The metric catalog and alert rules are in Prometheus & Grafana.

Zero-downtime deploy#

pboss deploy ecosystem.config.json production

Or manually:

git pull origin main
bun install
pboss reload all

reload cycles workers one at a time — new instances come up before old ones get SIGTERM. See Deployment and pboss reload.

Programmatic monitoring service#

import PBoss from "pboss";

const pboss = new PBoss();
await pboss.connect();

// Alert when any process uses more than 512 MB
pboss.on("metrics", (snapshot) => {
  for (const proc of snapshot.processes) {
    if (proc.memory > 512 * 1024 * 1024) {
      console.warn(`⚠️  ${proc.name} using ${Math.round(proc.memory / 1024 / 1024)} MB`);
    }
  }
});

pboss.startPolling(5000);

// Keep running
process.on("SIGINT", async () => {
  pboss.stopPolling();
  await pboss.disconnect();
  process.exit(0);
});

Programmatic deploy pipeline#

import PBoss from "pboss";

const pboss = new PBoss();
await pboss.connect();

// Deploy new code, then reload
console.log("Reloading all processes...");
const reloaded = await pboss.reload("all");
console.log(`Reloaded ${reloaded.length} processes`);

// Verify everything is healthy
const processes = await pboss.list();
const allOnline = processes.every((p) => p.status === "online");

if (allOnline) {
  console.log("✅ All processes online");
  await pboss.save();
} else {
  console.error("❌ Some processes failed to come online");
  const failed = processes.filter((p) => p.status !== "online");
  for (const p of failed) {
    console.error(`  ${p.name}: ${p.status}`);
  }
}

await pboss.disconnect();

Both examples use the same daemon-facing API the CLI uses — the full surface is in Programmatic API.