Prisma ORM 8 is here.Read the docs
Runtimes

Bun

Scaffold a Prisma ORM app with Bun, run your first typed query, serve users over HTTP, and deploy to Prisma Compute.

Introduction

In this guide, you scaffold a Prisma ORM project with Bun, initialize a PostgreSQL database from your schema, run your first typed query, serve query results over HTTP with Bun.serve, and deploy the server to Prisma Compute. Bun runs TypeScript directly, so nothing has to be compiled to work locally; the deploy bundles the server with tsdown.

Every command and code sample below was run end to end against a live Prisma Postgres database.

Prerequisites

  • Bun 1.1 or later (bun --version)
  • A PostgreSQL connection string, or nothing at all: bunx create-db can create a Prisma Postgres database for you

Use with your agent

To delegate this guide to your coding agent, copy the prompt below and hand it over:

Use with your agent
Use with your agent
Create a new Bun app with Prisma ORM, run a first typed query, and deploy it to Prisma Compute.

1. Scaffold: `bun create prisma@latest my-bun-app --template minimal --provider postgres --package-manager bun --yes`. Then run `bunx prisma@latest init` in `my-bun-app` so the Prisma agent skills are installed and stay current, and use them. Get a database connection string: use the one I give you, or create a Prisma Postgres database with `bunx create-db` and show me the claim URL it prints. Export it as `DATABASE_URL` in the shell; the generated scripts read the environment variable, not `.env`.
2. In `my-bun-app`, run `bun run contract:emit`, then `bun run db:init`, with `DATABASE_URL` exported.
3. Replace `src/index.ts` with a script that creates a user and reads all users back via `db.orm.public.User`, following https://www.prisma.io/docs/guides/runtimes/bun.md, and verify `bun src/index.ts` prints the created user (`bun run dev` is `tsx watch`, which does not exit).
4. Add `src/server.ts` with a `Bun.serve` server exposing GET /users, and verify `curl http://localhost:3000/users` returns the users.
5. Deploy: check `bunx prisma@latest auth whoami`; if I am not signed in, stop and ask me to run `bunx prisma@latest auth login`. Then point the build at the server by setting `entry` in `tsdown.config.ts` to `{ server: "src/server.ts" }`, run `bun run build`, then `bunx prisma@latest deploy module.ts`, and verify the live URL's /users endpoint returns `[]`. The deployed app provisions its own fresh Prisma Postgres database, so the local users are not there; do not pass the local DATABASE_URL. If the deploy fails with `HostedStateBootstrapError`, a project with the module's name exists in my workspace but its hosted state cannot be verified; re-run the deploy with `--name <a unique name>`.

Use the installed Prisma ORM skills.

1. Scaffold the project

Create the project with create-prisma. Pick Bun as the package manager when prompted, or pass everything up front:

bun create prisma@latest my-bun-app --template minimal --provider postgres --package-manager bun

Answer the prompts for contract authoring style. The scaffold sets up src/prisma/ with a starter schema and installs dependencies with Bun.

cd my-bun-app

Next, set the database connection for the local steps. Use your own PostgreSQL connection string, or create a Prisma Postgres database with bunx create-db; it prints a connection string and a claim URL you can open to keep the database. Export the variable in the shell you work in; the generated scripts read the environment variable, not .env:

export DATABASE_URL="<your connection string>"

2. Emit the contract and initialize the database

Prisma ORM compiles your schema (src/prisma/contract.prisma) into a contract that your queries are type-checked against. If you chose TypeScript authoring (--authoring typescript), the source is src/prisma/contract.ts and the emitted files land in src/prisma/generated/ instead. Emit it, then apply the schema to the database:

bun run contract:emit
bun run db:init

db:init creates the tables and signs the database:

"summary": "Applied 5 operation(s) across 1 space(s), database signed"

If db:init stops with Connection terminated unexpectedly, a database you just created is still starting; wait a few seconds and run it again. The command is safe to repeat and reports Applied 0 operation(s) when there is nothing left to do.

If db:init reports that the contract file is missing, run bun run contract:emit first; the emit step generates src/prisma/contract.json.

3. Write your first query

Replace src/index.ts with a script that creates a user and reads every user back. Model access is namespace-qualified on PostgreSQL: db.orm.public.User, where public is the default schema.

src/index.ts
import { db } from "./prisma/db";

// Create a user, then read every user back
const user = await db.orm.public.User.create({
  email: `ada+${Date.now()}@prisma.io`,
  name: "Ada Lovelace",
});
console.log(`created user ${user.email}`);

const users = await db.orm.public.User.select("id", "email", "name").all();
console.log(`there are now ${users.length} users`);

await db.close();

await db.close() at the end lets the script exit cleanly; without it, the connection pool keeps the process alive.

4. Run it

The generated dev script is tsx watch src/index.ts, which re-runs the file on every save. For a single run, call Bun directly:

bun src/index.ts
created user ada+1784893846026@prisma.io
there are now 1 users

The pg driver may print an SSL mode deprecation warning above the output; it comes from the sslmode=require setting in the generated connection string and does not affect the query.

That is the whole loop: schema to contract, contract to database, typed queries against both.

5. Serve it over HTTP

The script pattern works for one-off jobs. To keep the app running and serve query results, add a small HTTP server with Bun.serve. Create src/server.ts:

src/server.ts
import { db } from "./prisma/db";

const server = Bun.serve({
  port: Number(process.env.PORT ?? 3000),
  async fetch(req) {
    const { pathname } = new URL(req.url);
    if (pathname === "/users") {
      const users = await db.orm.public.User.select("id", "email", "name").all();
      return Response.json(users);
    }
    return new Response("Not found", { status: 404 });
  },
});

console.log(`Listening on http://localhost:${server.port}`);

Start it and check the endpoint:

bun src/server.ts
curl http://localhost:3000/users
[{ "id": 1, "email": "ada+1784893846026@prisma.io", "name": "Ada Lovelace" }]

The server listens on port 3000; set PORT to change it. Unlike the script, the server never calls db.close(): the connection pool is shared across requests and closes when the process exits.

6. Deploy to Prisma Compute

Plain Bun servers are supported on Prisma Compute. The scaffold declares the app for Prisma Composer in module.ts and service.ts, which deploy whatever the build script bundles into dist/server.mjs. That script runs tsdown, and the generated tsdown.config.ts sets its entry to src/index.ts, so point the entry at your server instead:

tsdown.config.ts
export default defineConfig({
  entry: { server: "src/server.ts" },
  // the rest of the generated config is unchanged
});

Sign in once (it opens a browser):

bunx prisma@latest auth login

Then build and deploy from the project directory:

bun run build
bunx prisma@latest deploy module.ts
my-bun-app
├─ database   postgres-database db_abc123
└─ app        compute-service cps_abc123
              https://xyz.ewr.prisma.build

The deploy creates a project named after your module in your workspace, and re-running the deploy reuses it: the CLI finds the hosted state it stored on the first run and converges the project to your module. If a project with that name exists but the CLI cannot identify or verify its stored state (one left behind by a different checkout, for example), the deploy stops with HostedStateBootstrapError; deploy under another name with --name <unique-name>, or rename the module in module.ts. The deploy also provisions its own Prisma Postgres database on the platform, declared in module.ts; the users you created locally are not in it. Verify the live endpoint responds with an empty list from the fresh database:

curl https://xyz.ewr.prisma.build/users
[]

For previews per Git branch and deploy-on-push, see Deploy your first app.

Prompt your coding agent

Run bunx prisma@latest init once to install the Prisma ORM skills for your coding agent and keep them matching your installed packages. Prompts that map to this guide:

  • "Using the prisma-8 skill, add a script that lists the 10 newest users."
  • "Add a published flag to the Post model in the starter contract, emit the contract, and update the database."

Next steps

On this page