Skip to content
DocsBackendDeploying a Backend

Deploying a Backend

Backends let you run arbitrary server-side code next to your PocketBase instance — REST APIs, webhook handlers, background workers, or a full Next.js app. Each backend runs in its own container with HTTPS and a dedicated subdomain.

Note: backend deployments require the Pro plan.

Supported runtimes

  • Node.js — the standard JavaScript runtime
  • Deno — TypeScript out of the box
  • Bun — fast all-in-one runtime
  • Next.js — deploy a full Next.js application with server-side rendering

Step 1: Prepare your app

Your app must listen on the port provided in the PORT environment variable — PocketBase Cloud injects it automatically:

// Node.js / Bun
const port = process.env.PORT || 3000;
app.listen(port);
// Deno
Deno.serve({ port: Number(Deno.env.get("PORT")) || 3000 }, handler);

Step 2: Deploy

Using the portal

  1. Open your project and go to the Backends tab
  2. Click New Backend
  3. Enter a name, choose a runtime, and set the start command (e.g., node index.js, deno run -A main.ts, or bun run index.ts)
  4. Click Create
  5. Zip your project directory (source files, package.json, lockfile — node_modules is not needed; dependencies install during deployment)
  6. On the backend’s Deploy page, upload the ZIP and click Deploy

Re-deploying is the same flow — upload a new ZIP and the container is replaced with the new version.

Using the CLI

cd api
pb cloud backend deploy --name my-app-api

One command builds, packages, uploads, creates the backend if needed, pushes a neighbouring .env, and waits for the container to reach running.

pb cloud deploy --name my-app-api does the same: a deno.json, a server dependency such as express or hono, a start script, or a next.config.* without output: "export" all identify a backend. See One deploy command for all three.

The first deploy records the backend in api/pb.json, so afterwards:

pb cloud backend deploy    # redeploy the linked backend

The runtime, build command, and start command are inferred from the directory (deno.json, bun.lockb, next.config.*, package.json) and written into pb.json. Review the guess before shipping with pb cloud init backend:

// api/pb.json
{
  "projectId": "dhs4xnprgplurvo",
  "kind": "backends",
  "defaultEnvironment": "production",
  "environments": {
    "production": { "id": "…", "name": "my-app-api" }
  },
  "build": {
    "runtime": "nodejs",
    "startCommand": "node index.js"
  }
}

Useful flags:

Flag What it does
--name <name> Which backend to deploy. Asked for when omitted and nothing is linked.
--runtime <deno|bun|nodejs|nextjs> Overrides build.runtime
--start <cmd> The command that boots the container
--compute <id> Compute to deploy onto. Asked for when the project owner has more than one — list them with pb cloud compute ls. (Formerly --server, still accepted.)
--skip-build Package without running the build command
--skip-env Don’t push the neighbouring .env
--zip <file> Upload an archive you built yourself
--env <name> Which pb.json environment to target

What gets packaged

deno, bun, and nodejs ship their source — the platform installs dependencies on start, so node_modules is excluded from the archive.

nextjs is different: the platform does not run next build (it exhausts memory on a shared host), so you ship a prebuilt bundle. That bundle exists only when the build asks for it, so the CLI adds output: "standalone" to next.config.* for you — before the build runs, printing the change — and writes a next.config.js if the project has none. A config that already sets output is left as it is. The CLI then assembles .next/standalone, .next/static, and public into the layout the runtime expects, starting it with node server.js:

// api/pb.json
{
  "build": { "command": "npm run build", "runtime": "nextjs" }
}

A config setting output: "export" is refused rather than rewritten — that is a static site, not a server, so deploy it as a frontend instead.

Uploading a Next.js ZIP by hand in the portal requires assembling that same layout yourself, which is the main reason to prefer the CLI for Next.js.

Your backend is live

Once the status turns running, your backend is live at:

https://<backend-name>.pocketbasecloud.com

Watch for that status on the Backends tab in the portal, or from the terminal:

pb cloud backend ls
pb cloud backend info --name my-app-api

Step 3: Connect to your PocketBase instance

Backends talk to PocketBase over its public URL like any other client, but with server-side credentials kept in environment variables:

import PocketBase from "pocketbase";

const pb = new PocketBase(process.env.POCKETBASE_URL);
await pb
  .collection("_superusers")
  .authWithPassword(process.env.PB_ADMIN_EMAIL, process.env.PB_ADMIN_PASSWORD);

Viewing logs

Using the portal

The backend detail page streams your container’s stdout/stderr in real time.

Using the CLI

pb cloud logs backend --name my-app-api            # last 50 lines
pb cloud logs backend --name my-app-api --lines 500
pb cloud logs backend --name my-app-api -f         # follow

Either way, the most common cause of a crash loop is listening on a hard-coded port instead of process.env.PORT.

Deleting a backend

Using the portal

Open the backend, go to its Delete page, and confirm.

Using the CLI

pb cloud backend rm --name my-app-api          # asks for confirmation
pb cloud backend rm --name my-app-api --yes    # scripted

Next steps