# Deploy the full Prisma stack (/docs/full-stack-tutorial)

> 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.

A single tutorial from empty directory to live URL, with Prisma Composer, Prisma 8, and Prisma Postgres.

Location: Deploy the full Prisma stack

This tutorial takes you through the whole recommended stack in one sitting. [Prisma Composer](https://www.prisma.io/docs/composer) declares your app: its services, its databases, and how they connect. [Prisma 8](https://www.prisma.io/docs/orm) types your data. [Prisma Postgres](https://www.prisma.io/docs/postgres) stores it, locally while you develop and on the platform when you deploy. One declaration drives everything: the same `module.ts` runs the app on your machine and deploys it to [Prisma Compute](https://www.prisma.io/docs/compute). Plan on about 15 minutes.

It uses the `hono` template so you get a small API you can verify with curl at every step. The same journey works for the other templates; the [framework guides](https://www.prisma.io/docs/guides) cover each one.

## Prerequisites [#prerequisites]

* Node.js 24 or later (or Bun)
* A [Prisma Data Platform account](https://pris.ly/pdp) for the deploy step, free to create
* No database needed: local runs provision a local Prisma Postgres, and deploys provision a real one, both from your Composer declaration

## Use with your agent [#use-with-your-agent]

If you would rather hand the work to a coding agent, this prompt runs the same journey as the one on the [getting started page](https://www.prisma.io/docs), with the `hono` template chosen for you:

```text
Create a new Hono API composed with Prisma Composer and Prisma 8, run it locally, and deploy it to Prisma Compute.

1. Scaffold: `npx create-prisma@latest create my-app --template hono --provider postgres --yes`. Then run `npx prisma@latest init` in `my-app` so the Prisma agent skills are installed and stay current, and use them.
2. Read `module.ts` and `service.ts` first: the Composer module provisions the database and the service, and it is what `dev` and `deploy` operate on.
3. Build and run locally: `npm run build`, then `npx prisma@latest dev module.ts`. This provisions a local Prisma Postgres database and applies the contract; no DATABASE_URL is needed. Sample users are seeded on the app's first query. Verify the local URL that `dev` prints: its /users endpoint returns the seeded users.
4. Deploy: check `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). Capture the baseline migration first with `npx prisma@latest migration plan --name init` and note the migration directory it writes. Then run `npx prisma@latest deploy module.ts` and verify the live URL's /users endpoint with curl. The deploy creates the project and provisions the database from the module declaration; do not pass a DATABASE_URL.
5. Evolve the schema: add `role String @default("member")` to the User model in `src/prisma/contract.prisma`, run `npx prisma@latest contract emit`, add `"role"` to the typed select and the returned object in `src/prisma/users.ts`, and plan the migration with `npx prisma@latest migration plan --name add-user-role --from <the init migration directory>`. Then run `npm run build` and `npx prisma@latest deploy module.ts` again, and verify the live /users now returns `role: "member"` with the same createdAt values as before.
```

## 1. Scaffold the app [#1-scaffold-the-app]

One command creates a Composer-declared app with Prisma 8 wired in:

  

#### bun

```bash
bunx create-prisma@latest create my-app --template hono --provider postgres
```

#### pnpm

```bash
pnpm dlx create-prisma@latest create my-app --template hono --provider postgres
```

#### yarn

```bash
yarn dlx create-prisma@latest create my-app --template hono --provider postgres
```

#### npm

```bash
npx create-prisma@latest create my-app --template hono --provider postgres
```

Answer the prompts for contract authoring style and package manager, then enter the project:

  

#### bun

```bash
cd my-app
```

#### pnpm

```bash
cd my-app
```

#### yarn

```bash
cd my-app
```

#### npm

```bash
cd my-app
```

If you work with a coding agent, run [`npx prisma@latest init`](https://www.prisma.io/docs/cli/init) once. The scaffold has already synced the [Prisma agent skills](https://www.prisma.io/docs/ai/tools/skills) that ship inside its Prisma packages and added the `postinstall` hook that keeps them current, so on a fresh scaffold `init` confirms that setup and reports each step as already done. It is still worth running, because it is the command that repairs the setup after you upgrade a Prisma package. See [`skills`](https://www.prisma.io/docs/cli/skills).

## 2. The Composer app [#2-the-composer-app]

Start with the declaration, because it is what every later command operates on. The scaffold declares the whole app in two files. `module.ts` is the app: it provisions a Prisma Postgres database and the service, and wires one to the other:

```ts title="module.ts"
import { module } from "@prisma/composer";
import { postgres } from "@prisma/composer-prisma-cloud/orm";

import { appContract } from "./src/prisma/composer.ts";
import app from "./service.ts";

export default module("my-app", ({ provision }) => {
  const database = provision(
    postgres({
      name: "database",
      contract: appContract,
      config: "./prisma.config.ts",
    }),
    { id: "database" },
  );

  provision(app, { deps: { database } });
});
```

`service.ts` declares the service itself: its name, its dependency on the database, and how it is built:

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

import { appContract } from "./src/prisma/composer.ts";

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

Notice there is no connection string anywhere. The database is a declared dependency, typed by your contract, and Composer injects the connection wherever the app runs. The declaration is ordinary TypeScript: `npx tsc --noEmit` checks the wiring, and mistakes fail the compile instead of a deploy. [Composer](https://www.prisma.io/docs/composer) covers the model in full: modules, services, dependencies, and the first-party building blocks.

## 3. The Prisma 8 data model [#3-the-prisma-8-data-model]

The data side lives under `src/prisma/`. Your schema is the starter contract in `src/prisma/contract.prisma`; `npm run contract:emit` compiles it into the contract artifacts your queries are type-checked against, and `src/prisma/db.ts` is the typed client the route handlers import. The `/users` route in `src/index.ts` is ordinary Hono code calling an ordinary Prisma 8 query.

Change the contract when you are ready to model your own data, re-emit it, and the compiler walks you through every query the change touches. The [fundamentals](https://www.prisma.io/docs/orm/fundamentals/reading-data) cover the query patterns.

## 4. Run it locally on Prisma Postgres [#4-run-it-locally-on-prisma-postgres]

Build the server, then bring the whole declaration up on your machine:

  

#### 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 Prisma Postgres database, applies the contract to it, starts the service, and prints the app's local URL when everything is ready. No account, credentials, or connection string are involved; see [Local development](https://www.prisma.io/docs/local-development) for how the local platform works.

Sample users are seeded automatically the first time the app queries the database. Confirm the API serves the seeded rows. `dev` picks a free port and prints the URL, so use the one it printed if it differs from the `3000` shown here:

```bash
curl http://localhost:3000/users
```

```json no-copy
[
  { "id": "1", "email": "alice@prisma.io", "username": "alice", "name": "Alice", "createdAt": "2026-08-24T13:51:34.797Z" },
  { "id": "2", "email": "bob@prisma.io", "username": "bob", "name": "Bob", "createdAt": "2026-08-24T13:51:34.803Z" },
  { "id": "3", "email": "carol@prisma.io", "username": "carol", "name": "Carol", "createdAt": "2026-08-24T13:51:34.804Z" }
]
```

If you prefer the framework's own dev server, `npm run dev` runs it directly. Composer does not manage that mode, so the app needs a database of your own in `DATABASE_URL`. Create one inside your project with the CLI:

  

#### bun

```bash
bunx prisma@latest auth login
bunx prisma@latest project create my-app
bunx prisma@latest postgres create mydb
```

#### pnpm

```bash
pnpm dlx prisma@latest auth login
pnpm dlx prisma@latest project create my-app
pnpm dlx prisma@latest postgres create mydb
```

#### yarn

```bash
yarn dlx prisma@latest auth login
yarn dlx prisma@latest project create my-app
yarn dlx prisma@latest postgres create mydb
```

#### npm

```bash
npx prisma@latest auth login
npx prisma@latest project create my-app
npx prisma@latest postgres create mydb
```

`postgres create` prints the connection string once; export it as `DATABASE_URL`, and mint another later with `npx prisma@latest postgres connection create mydb` if you need one. The `db:*` scripts in `package.json` initialize and verify that database. See [`postgres`](https://www.prisma.io/docs/cli/postgres).

## 5. Deploy app and database to Prisma Compute [#5-deploy-app-and-database-to-prisma-compute]

Sign in once (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
```

Before the first deploy, capture your schema as the first checked-in migration. Deployed databases evolve through the migrations you commit, so the baseline must be one:

  

#### bun

```bash
bunx prisma@latest migration plan --name init
```

#### pnpm

```bash
pnpm dlx prisma@latest migration plan --name init
```

#### yarn

```bash
yarn dlx prisma@latest migration plan --name init
```

#### npm

```bash
npx prisma@latest migration plan --name init
```

The plan writes `migrations/app/<timestamp>_init`; commit it with your code. You will chain the next migration from it in [step 7](#7-evolve-the-data-model).

Build and deploy the same declaration:

  

#### 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
```

Composer creates a project named after your module, provisions the Prisma Postgres database declared in `module.ts`, wires it to the service, and starts the app. There is nothing to configure and no environment file to pass, because the deployed database comes from the declaration exactly as the local one did. When everything is up, the deploy prints what it made, each part of your app next to the platform resource it became, along with the public URL:

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

> [!WARNING]
> The module name must be unique in your workspace
> 
> `deploy` looks the module name up in your workspace and reuses the project this module deployed before rather than creating another. If a `my-app` project exists whose hosted state the CLI cannot verify (one deployed from a different checkout, for example), the deploy stops with `HostedStateBootstrapError` and names a project id you did not choose. Deploy under a different name with [`--name`](https://www.prisma.io/docs/cli/deploy#flags), or rename the module in `module.ts`:
> 
> 
>   
> 
>   #### bun

>     ```bash
>     bunx prisma@latest deploy module.ts --name my-app-tutorial
>     ```
>
> 
>   #### pnpm

>     ```bash
>     pnpm dlx prisma@latest deploy module.ts --name my-app-tutorial
>     ```
>
> 
>   #### yarn

>     ```bash
>     yarn dlx prisma@latest deploy module.ts --name my-app-tutorial
>     ```
>
> 
>   #### npm

>     ```bash
>     npx prisma@latest deploy module.ts --name my-app-tutorial
>     ```
>
> 

## 6. Verify the live URL [#6-verify-the-live-url]

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

The same three users come back, now served from production next to your database, seeded on the deployed app's first query. Re-deploying is idempotent: build again, deploy again, and the platform applies only the difference. That includes removals, because your module is the source of truth: delete a provision from `module.ts`, deploy again, and the resource disappears from the platform. See [Removing resources](https://www.prisma.io/docs/composer/deploying#removing-resources).

## 7. Evolve the data model [#7-evolve-the-data-model]

Live apps outgrow their starter schema, so give users a role. Add one line to the contract:

```prisma title="src/prisma/contract.prisma"
model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  username  String?
  name      String?
  role      String   @default("member")
  posts     Post[]
  createdAt DateTime @default(now())
  updatedAt temporal.updatedAt()
}
```

Re-emit the contract, then plan the migration that carries the change, chaining from the baseline migration you created in [step 5](#5-deploy-app-and-database-to-prisma-compute):

  

#### bun

```bash
bunx prisma@latest contract emit
bunx prisma@latest migration plan --name add-user-role --from <timestamp>_init
```

#### pnpm

```bash
pnpm dlx prisma@latest contract emit
pnpm dlx prisma@latest migration plan --name add-user-role --from <timestamp>_init
```

#### yarn

```bash
yarn dlx prisma@latest contract emit
yarn dlx prisma@latest migration plan --name add-user-role --from <timestamp>_init
```

#### npm

```bash
npx prisma@latest contract emit
npx prisma@latest migration plan --name add-user-role --from <timestamp>_init
```

`--from` names the migration you are building on, and here it is required: a Composer deploy never sets the `db` ref that `migration plan` chains from by default, so a plan without it would describe every table again. The [`migration plan`](https://www.prisma.io/docs/cli/migration-plan) and [`migration ref`](https://www.prisma.io/docs/cli/migration-ref) references cover the default, the ref, and how to keep plans chaining on their own.

The plan is your change and nothing else. Review it like any other diff, with [`migration show`](https://www.prisma.io/docs/cli/migration-show) or by reading the generated package:

```text no-copy
ALTER TABLE "public"."user" ADD COLUMN "role" text DEFAULT 'member' NOT NULL
```

Emitting also updated the query types, so surface the new field in the route's typed select in `src/prisma/users.ts`, adding `"role"` to the `.select(...)` list and `role: user.role` to the returned object:

```ts title="src/prisma/users.ts"
const users = await db.orm.public.User.select("id", "email", "username", "name", "role", "createdAt").take(limit).all();
```

This is the Prisma 8 loop: the contract is the source of truth, the emit step regenerates the types, and the compiler points at every query the change touches.

If you want to see the change on your machine first, run `npm run build` and `npx prisma@latest dev module.ts` again; the local database applies the new migration on start and `/users` returns the role there too. Then build and deploy again:

  

#### 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 deploy applies the committed migration to the deployed database in place. The same users come back with `role: "member"`, backfilled by the column default, and their `createdAt` timestamps unchanged; nothing was dropped or recreated:

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

```json no-copy
[
  { "id": "1", "email": "alice@prisma.io", "username": "alice", "name": "Alice", "role": "member", "createdAt": "2026-08-24T18:40:06.375Z" }
]
```

## 8. Clean up (optional) [#8-clean-up-optional]

The project keeps running until you remove it. Deleting it removes the service and the database, so the command asks you to repeat the project id (find it with `npx prisma@latest project list`):

  

#### bun

```bash
bunx prisma@latest project delete <project-id> --confirm <project-id>
```

#### pnpm

```bash
pnpm dlx prisma@latest project delete <project-id> --confirm <project-id>
```

#### yarn

```bash
yarn dlx prisma@latest project delete <project-id> --confirm <project-id>
```

#### npm

```bash
npx prisma@latest project delete <project-id> --confirm <project-id>
```

## Next steps [#next-steps]

* [Learn Composer](https://www.prisma.io/docs/composer/getting-started): typed contracts between services, databases, storage, and scheduled jobs.
* [Pick your framework](https://www.prisma.io/docs/guides): the same journey for Next.js, Nuxt, Astro, NestJS, TanStack Start, and more.
* [Branching and previews](https://www.prisma.io/docs/compute/branching): every Git branch gets an isolated deployment.
* [Learn the fundamentals](https://www.prisma.io/docs/orm/fundamentals/reading-data): reading, writing, relations, and transactions.
* [Deploy on push](https://www.prisma.io/docs/compute/deploy-on-push): connect GitHub so every commit deploys itself, with a preview environment per branch.

## Related pages

- [`Choose a Prisma 8 setup path`](https://www.prisma.io/docs/getting-started): Choose the fastest path to try Prisma 8 in a new or existing project.
- [`Console`](https://www.prisma.io/docs/console): Learn how to use the Console to manage and integrate Prisma products into your application.
- [`Introduction to Prisma 8`](https://www.prisma.io/docs/prisma-orm): Prisma 8 is the current release of Prisma ORM.
- [`Local development`](https://www.prisma.io/docs/local-development): Run the whole Prisma stack on your machine, with your app on Bun, a local Prisma Postgres database, and local object storage.
- [`Overview`](https://www.prisma.io/docs/cli): Prisma CLI reference