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: Create the backend
- Open your project and go to the Backends tab
- Click New Backend
- Enter a name, choose a runtime, and set the start command
(e.g.,
node index.js,deno run -A main.ts, orbun run index.ts) - Click Create
Step 3: Deploy your code
- Zip your project directory (source files,
package.json, lockfile —node_modulesis not needed; dependencies install during deployment) - On the backend’s Deploy page, upload the ZIP
- Click Deploy
PocketBase Cloud uploads the archive to the server, installs dependencies, starts the container, and wires up DNS + HTTPS. Once the status turns running, your backend is live at:
https://<backend-name>.pocketbasecloud.com
Re-deploying is the same flow — upload a new ZIP and the container is replaced with the new version.
Step 4: 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
The backend detail page streams your container’s stdout/stderr in real time —
useful for debugging failed starts. The most common cause of a crash loop is
listening on a hard-coded port instead of process.env.PORT.