# Deploy your first app (/docs/prisma-compute/deploy)

> For the complete Prisma documentation index, see [llms.txt](https://www.prisma.io/docs/llms.txt). A markdown version of any docs page is available by appending `.md` to its URL.

Take a TypeScript app from your terminal to a live URL on Prisma Compute with Prisma Composer, starting from scratch or from an app you already have.

Location: Prisma Compute > Deploy your first app

[Prisma Compute](https://www.prisma.io/docs/compute) is serverless hosting for TypeScript apps. It runs your app right next to your Prisma Postgres database, so the trip from app to data stays short. Apps are declared and deployed with [Prisma Composer](https://www.prisma.io/docs/composer): you describe your app's services in TypeScript, and one command stands them up on Compute. By the end of this page you have a live URL.

Start from wherever you are:

* **You're starting from scratch.** [Declare a new app](#start-from-scratch) and run it locally, then deploy it.
* **You already have an app.** [Add a declaration around your server code](#bring-an-app-you-already-have), then deploy it.

Both paths meet in the same [deploy step](#2-deploy), because Composer treats every app the same way. A deployed app becomes a **project**, deploying with no flags targets **production**, and `--stage <name>` deploys an isolated copy of the whole app as a [preview branch](https://www.prisma.io/docs/compute/branching) of the same project. Local runs never talk to the platform, so you need credentials only when you deploy. For the platform's resource model, see [Compute](https://www.prisma.io/docs/compute#the-model).

## Prerequisites [#prerequisites]

Before you start, make sure you have:

* **Node.js 22.18 or newer.** Composer hands your TypeScript entry file straight to Node, and running `.ts` files directly needs 22.18.0 or later. On older versions, Composer commands stop at `ERR_UNKNOWN_FILE_EXTENSION`.
* **[Bun](https://bun.sh).** Prisma Compute runs deployed apps on Bun, so your server code targets it, and `bun build` produces the self-contained entry file a deploy needs.
* **A [Prisma Data Platform account](https://pris.ly/pdp)**, free to create. You only need it for the deploy step; [local development](https://www.prisma.io/docs/local-development) runs without an account.

## 1. Get an app declared with Composer [#1-get-an-app-declared-with-composer]

A Composer app is your server code plus a small declaration: what each service is called, how it is built, and what it depends on. Pick the path that matches your starting point.

### Start from scratch [#start-from-scratch]

Set up the project as in [Composer getting started, step 1](https://www.prisma.io/docs/composer/getting-started#1-set-up-the-project): install `@prisma/composer` and `@prisma/composer-prisma-cloud`, pin the `effect` family, and add the `tsconfig.json`. Then a minimal one-service app is four files.

The **server** is ordinary Bun code. The one Composer-specific line reads the port from `service.port()`; bind `0.0.0.0`, because Compute routes external HTTP to the VM and a loopback-only listener would be unreachable:

```ts title="src/server.ts"
import service from "./service.ts";

Bun.serve({
  port: service.port(),
  hostname: "0.0.0.0",
  fetch: () => new Response("Hello from Prisma Compute"),
});
```

The **service declaration** names the service and points at your built output:

```ts title="src/service.ts"
import node from "@prisma/composer/node";
import { compute } from "@prisma/composer-prisma-cloud";

export default compute({
  name: "web",
  deps: {},
  build: node({ module: import.meta.url, entry: "../dist/server.mjs" }),
});
```

The **root module** is the app: it provisions the service. The **deploy config** next to it is read only by the CLI:

```ts title="module.ts"
import { module } from "@prisma/composer";
import webService from "./src/service.ts";

export default module("my-app", ({ provision }) => {
  provision(webService);
});
```

```ts title="prisma-composer.config.ts"
import { defineConfig } from "@prisma/composer/config";
import { nodeBuild } from "@prisma/composer/node/control";
import { prismaCloud, prismaState } from "@prisma/composer-prisma-cloud/control";

export default defineConfig({
  extensions: [prismaCloud(), nodeBuild()],
  state: prismaState(),
});
```

You own the build; Composer assembles what you built. Add a build script that produces one self-contained file per service:

```json title="package.json"
{
  "scripts": {
    "build": "bun build src/server.ts --target=bun --outfile dist/server.mjs"
  }
}
```

Now run the app on your machine. No account or credentials are involved:

  

#### bun

```bash
bun run build
bunx prisma@latest dev module.ts
```

#### pnpm

```bash
pnpm run build
pnpm dlx prisma@latest dev module.ts
```

#### yarn

```bash
yarn build
yarn dlx prisma@latest dev module.ts
```

#### npm

```bash
npm run build
npx prisma@latest dev module.ts
```

`dev` prints the service's local URL; `curl` it and you get `Hello from Prisma Compute`. See [Local development](https://www.prisma.io/docs/local-development) for the local database, storage, and log workflow.

From here the app grows by declaration: `deps: { db: postgres() }` gives the service a [Prisma Postgres database](https://www.prisma.io/docs/composer/databases), [`bucket()`](https://www.prisma.io/docs/composer/object-storage) gives it object storage, and a second service with a [typed contract](https://www.prisma.io/docs/composer/getting-started) turns cross-service calls into checked function calls. When the app runs locally, continue to [Deploy](#2-deploy).

### Bring an app you already have [#bring-an-app-you-already-have]

Porting an app does not mean rewriting it. Your server code stays the server, your build stays the build, and you add a declaration around them. The steps below port a two-service app, a notes API on Postgres and an uploads service on S3 credentials, to a Composer app that provisions its own database and bucket. For a Next.js service, use the `nextjs` build adapter with `output: "standalone"` instead; [Port an existing app](https://www.prisma.io/docs/composer/porting-an-app) covers that variant.

**1. Install the Composer packages.** Same as [step 1 of the scratch path](https://www.prisma.io/docs/composer/getting-started#1-set-up-the-project): install `@prisma/composer` and `@prisma/composer-prisma-cloud`, and pin `effect` to the version your installed `@prisma/composer` requires.

**2. Declare each service.** A `service.ts` next to each server names the service, declares what it consumes as dependencies, and points at your built output. A Postgres connection becomes `postgres()`; S3 credentials become `bucket()`:

```ts title="src/api/service.ts"
import node from "@prisma/composer/node";
import { compute, postgres } from "@prisma/composer-prisma-cloud";

export default compute({
  name: "api",
  deps: { db: postgres() },
  build: node({ module: import.meta.url, entry: "../../dist/api.mjs" }),
});
```

```ts title="src/files/service.ts"
import node from "@prisma/composer/node";
import { bucket, compute } from "@prisma/composer-prisma-cloud";

export default compute({
  name: "files",
  deps: { store: bucket() },
  build: node({ module: import.meta.url, entry: "../../dist/files.mjs" }),
});
```

**3. Provision everything in one module.** The root module owns the resources and wires them to the services; the deploy config next to it is the same one the scratch path uses:

```ts title="module.ts"
import { module } from "@prisma/composer";
import { bucket, postgres } from "@prisma/composer-prisma-cloud";
import apiService from "./src/api/service.ts";
import filesService from "./src/files/service.ts";

export default module("my-app", ({ provision }) => {
  const db = provision(postgres({ name: "database" }));
  const store = provision(bucket({ name: "uploads" }));
  provision(apiService, { deps: { db } });
  provision(filesService, { deps: { store } });
});
```

**4. Port the environment reads.** This is the only change to your server code, and it is what makes every environment work without hand-wired configuration:

1. **The port**: read `service.port()` instead of `process.env.PORT`, and bind `0.0.0.0`.
2. **Dependency values**: read `service.load()` instead of connection-string and credential env vars. The Postgres dependency delivers `db.url` for whatever client you already use; the bucket delivers the standard S3 set.
3. **Everything else** (flags, regions, external URLs, third-party credentials) becomes the service's [input schema](https://www.prisma.io/docs/composer/service-input).

```ts title="src/api/server.ts (the changed lines)"
import { SQL } from "bun";
import service from "./service.ts";

// before: new SQL({ url: process.env.DATABASE_URL })
const { db } = service.load();
const sql = new SQL({ url: db.url, max: 1, idleTimeout: 10 });

Bun.serve({ port: service.port(), hostname: "0.0.0.0", fetch: handler });
```

```ts title="src/files/server.ts (the changed lines)"
import service from "./service.ts";

// before: endpoint, bucket, and keys from four S3_* env vars
const { store } = service.load();
const s3 = new Bun.S3Client({
  endpoint: store.url,
  bucket: store.bucket,
  accessKeyId: store.accessKeyId,
  secretAccessKey: store.secretAccessKey,
});
```

**5. Build and verify locally.** Your build must produce one self-contained entry file per service; keep your own build if it already does, or use one `bun build --target=bun` line per service. Then run the whole declaration locally:

  

#### bun

```bash
bun run build
bunx prisma@latest dev module.ts
```

#### pnpm

```bash
pnpm run build
pnpm dlx prisma@latest dev module.ts
```

#### yarn

```bash
yarn build
yarn dlx prisma@latest dev module.ts
```

#### npm

```bash
npm run build
npx prisma@latest dev module.ts
```

`dev` provisions a local Postgres and a local stand-in bucket with working credentials, and every service appears in the startup output with a local URL, so you can exercise the database and upload paths end-to-end before touching the platform. Then continue to [Deploy](#2-deploy): the same deploy command provisions the real database and bucket alongside the services.

## 2. Deploy [#2-deploy]

Sign in once. This is the only interactive step, because it opens your browser:

  

#### bun

```bash
bunx prisma@latest auth login
```

#### pnpm

```bash
pnpm dlx prisma@latest auth login
```

#### yarn

```bash
yarn dlx prisma@latest auth login
```

#### npm

```bash
npx prisma@latest auth login
```

The session is stored on your machine and every later command reads it, including commands a coding agent runs in your directory. Confirm it any time with `auth whoami`. In CI or a headless environment, set `PRISMA_SERVICE_TOKEN` and `PRISMA_WORKSPACE_ID` instead; see [Deploying](https://www.prisma.io/docs/composer/deploying#credentials).

`deploy` does not build for you, so build first, then deploy:

  

#### bun

```bash
bun run build
bunx prisma@latest deploy module.ts
```

#### pnpm

```bash
pnpm run build
pnpm dlx prisma@latest deploy module.ts
```

#### yarn

```bash
yarn build
yarn dlx prisma@latest deploy module.ts
```

#### npm

```bash
npm run build
npx prisma@latest deploy module.ts
```

The CLI creates a project named after your root module, provisions the services on Compute and any databases on Prisma Postgres, wires the dependencies, and starts everything. The project name identifies the app in your workspace: redeploying reuses the project this module created, and a same-name project whose hosted state the CLI cannot verify stops the command with `HostedStateBootstrapError`. Deploy under another name with `--name <unique-name>` when that happens.

## 3. Verify the deployment [#3-verify-the-deployment]

A deploy finishes by printing what it made: each service, the platform resource it became, and its public URL:

```text no-copy
my-app
└─ web   compute-service cps_abc123
         https://xyz.ewr.prisma.build
```

Request the printed URL to confirm the app responds:

```bash
curl https://xyz.ewr.prisma.build
```

You can also inspect everything in the [Console](https://pris.ly/pdp): projects, branches, services, deployments, and domains.

## 4. Ship changes and environments [#4-ship-changes-and-environments]

Re-deploying is idempotent: build again, deploy again, and the platform applies the difference instead of recreating everything. That includes removals: delete a provision from your module and the next deploy deletes the resource; see [Removing resources](https://www.prisma.io/docs/composer/deploying#removing-resources). Production and previews are separated by stages:

  

#### bun

```bash
bunx prisma@latest deploy module.ts                  # production
bunx prisma@latest deploy module.ts --stage staging  # a persistent staging environment
bunx prisma@latest deploy module.ts --stage pr-42    # one environment per PR
```

#### pnpm

```bash
pnpm dlx prisma@latest deploy module.ts                  # production
pnpm dlx prisma@latest deploy module.ts --stage staging  # a persistent staging environment
pnpm dlx prisma@latest deploy module.ts --stage pr-42    # one environment per PR
```

#### yarn

```bash
yarn dlx prisma@latest deploy module.ts                  # production
yarn dlx prisma@latest deploy module.ts --stage staging  # a persistent staging environment
yarn dlx prisma@latest deploy module.ts --stage pr-42    # one environment per PR
```

#### npm

```bash
npx prisma@latest deploy module.ts                  # production
npx prisma@latest deploy module.ts --stage staging  # a persistent staging environment
npx prisma@latest deploy module.ts --stage pr-42    # one environment per PR
```

A stage is a complete, isolated copy of the app: its own services, databases, and configuration, sharing only the code with production. In platform terms it is a [preview branch](https://www.prisma.io/docs/compute/branching) of the same project. Tearing a stage down needs the control API with service-token credentials, or a branch deletion in the Console; see [Destroying](https://www.prisma.io/docs/composer/deploying#destroying). [Deploying](https://www.prisma.io/docs/composer/deploying) covers CI, deploy state, and teardown in full.

## Hand it to your agent [#hand-it-to-your-agent]

You can let a coding agent do the work. Sign in once yourself ([step 2](#2-deploy)). The browser sign-in is the one step an agent can't do for you. After that, anything running in your environment inherits the session, including your agent. The `@prisma/composer` package ships an [agent skill](https://www.prisma.io/docs/cli/skills) that teaches your agent the installed version's API; [`npx prisma@latest init`](https://www.prisma.io/docs/cli/init) sets the project up so the skill stays in sync across upgrades. Paste this into your agent and fill in the blanks:

```text
Build [what you want] as a Prisma Composer app and deploy it to Prisma Compute using `npx prisma@latest`.

Notes:
- After installing @prisma/composer, install its agent skill so you use the real API: `npx prisma@latest skills sync` (the skill ships inside the package; run `npx prisma@latest skills list` to confirm).
- Before deploying, run `npx prisma@latest auth whoami`; if I am not signed in, stop and ask me to run `npx prisma@latest auth login` (it opens a browser).
- Composer needs Node.js 22.18 or newer, and server code targets Bun. Read the port with `service.port()` and bind 0.0.0.0. For a Next.js service, use the nextjs build adapter and set `output: "standalone"`.
- Composer does not build; produce one self-contained entry file per service (for example `bun build --target=bun`), then run it locally with `npx prisma@latest dev module.ts` and verify each service's local URL responds.
- Deploy with `npx prisma@latest deploy module.ts` and verify the printed public URL with curl.
- To give a service a database, declare `deps: { db: postgres() }` and build the client from the injected `db.url`; do not read connection strings from process.env.
- Current docs: https://www.prisma.io/docs/composer.md and https://www.prisma.io/docs/prisma-compute/deploy.md
```

For example:

```text
Build a Bun API with a /todos endpoint backed by an in-memory list as a Prisma Composer app and deploy it to Prisma Compute using `npx prisma@latest`.
```

## What's next [#whats-next]

* [Composer getting started](https://www.prisma.io/docs/composer/getting-started): the two-service version, with a typed contract between services.
* [Databases](https://www.prisma.io/docs/composer/databases): give a service a Prisma Postgres database, plain or typed by a Prisma 8 contract.
* [Deploying](https://www.prisma.io/docs/composer/deploying): stages, CI, deploy state, and teardown.
* [Local development](https://www.prisma.io/docs/local-development): run the app, database, and storage on your machine with the runtime you deploy.