# Start a TypeScript app with Postgres on Prisma for free (/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. From an empty directory to a live TypeScript app with a Prisma Postgres database on Prisma Compute, with the Free plan limits listed. Location: Start a TypeScript app with Postgres on Prisma for free The fastest path to a TypeScript app with a Postgres database on Prisma is the CLI: it scaffolds the app, runs it on a local [Prisma Postgres](https://www.prisma.io/docs/postgres) database with no account, and, once you sign in, deploys it to [Prisma Compute](https://www.prisma.io/docs/compute) and creates its database there. Everything runs on the [Free plan](#what-the-free-plan-includes) with no credit card. The steps below do it by hand, and the prompt under [Use with your agent](#use-with-your-agent) runs the same journey end to end. [Prisma Composer](https://www.prisma.io/docs/composer) declares your app: its services, its databases, and how they connect. [Prisma ORM](https://www.prisma.io/docs/orm) types your data. Prisma 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. 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 22.18 or newer (on the 24 line, 24.11 or newer; 24 recommended), or Bun * npm 11.6.0 or newer, if you use npm. Node.js 22 comes with npm 10, so run `npm install --global npm@11` first; the [create-prisma prerequisites](https://www.prisma.io/docs/prisma-orm/create-prisma#prerequisites) explain why * A [Prisma Data Platform account](https://pris.ly/pdp) for the deploy step, free to create, with no credit card needed on the [Free plan](#what-the-free-plan-includes) * No database needed: local runs provision a local Prisma Postgres, and deploys provision a real one, both from your Composer declaration > [!NOTE] > Already have an app? > > Keep your code and add a small Prisma Composer declaration next to it: a `service.ts` for each server and one `module.ts`. The server reads its port from `service.port()` and binds `0.0.0.0`; [Port an existing app](https://www.prisma.io/docs/composer/porting-an-app) lists the other changes and has an agent prompt that makes them, and [Bring an app you already have](https://www.prisma.io/docs/prisma-compute/deploy#bring-an-app-you-already-have) is a worked example. Once `npm run build` and `npx prisma dev module.ts` run it, continue at [step 5](#5-deploy-app-and-database-to-prisma-compute). SvelteKit and Deno apps do not deploy to Prisma Compute yet. ## What the Free plan includes [#what-the-free-plan-includes] Everything in this tutorial runs on the Free plan: $0 a month, no credit card, no time limit, and no usage billing. The limits below are the ones on the [pricing page](https://www.prisma.io/pricing), which also lists the paid plans. They apply to your whole [workspace](https://www.prisma.io/docs/console/concepts#workspace), the billing unit of your Prisma account that holds all of your projects and databases, so each number is shared across everything in the workspace, not granted to each database. Prisma ORM is optional on both products: Prisma Postgres works with any PostgreSQL client, and Compute runs apps that do not use Prisma ORM. See [Do I need Prisma ORM to use Compute?](https://www.prisma.io/docs/compute/faq#do-i-need-prisma-orm-to-use-compute). The scaffold in this tutorial uses Prisma ORM 8, which is a release candidate; see [Release status](https://www.prisma.io/docs/orm/release-status). ### Prisma Postgres [#prisma-postgres] | Limit | Free plan | | ------------------ | --------------- | | Operations | 200,000 a month | | Storage | 1.01 GB | | Databases | 50 | | Data transfer | Unlimited | | Pooled connections | 10 | | Direct connections | 10 | | Automated backups | None | Each query is one operation, whether it reads or writes. See [What is an operation?](https://www.prisma.io/docs/postgres/faq#what-is-an-operation). Direct connections are the ones PostgreSQL tools such as `pg_dump` open, and 5 of the 10 are reserved for platform operations; see [Connection limits](https://www.prisma.io/docs/postgres/database/connection-pooling#connection-limits). The Free plan has no automated backups, and Prisma Postgres cannot yet restore a database to an earlier point in time, so keep your own copies with `pg_dump`, the PostgreSQL command-line backup tool, over a direct connection. See [Backups](https://www.prisma.io/docs/postgres/database/backups). ### Prisma Compute [#prisma-compute] | Meter | Free plan | | ------------------ | -------------------- | | Requests | 1,000,000 a month | | Provisioned memory | 360 GB-hours a month | | Active CPU | 4 vCPU-hours a month | | Outbound bandwidth | 10 GB a month | A GB-hour is one gigabyte of memory allocated for one hour, and a vCPU-hour is one virtual CPU in use for one hour. Memory counts only while the app is running or you have chosen to keep it awake, because an idle app scales to zero: it stops running and costs nothing while idle. Outbound bandwidth is the data your app sends out to the internet, and incoming requests do not count. It is separate from the database's unlimited data transfer: Compute includes 10 GB of outbound bandwidth a month on Free. See [Compute pricing](https://www.prisma.io/docs/compute/pricing) for what each meter measures. ### Check your usage and upgrade [#check-your-usage-and-upgrade] The Free plan has no usage billing, so reaching a limit does not add a charge. Operations and the four Compute meters are monthly limits, while storage and the number of databases are not tied to a month. To see how much a database has used, run `npx prisma postgres usage `, or track usage in the [Prisma Console](https://console.prisma.io/?utm_source=docs\&utm_medium=content\&utm_content=%28index%29); see [Billing and limits](https://www.prisma.io/docs/postgres#billing-and-limits). Usage reporting for Compute in the CLI and API is still being built. To go past a limit, move the workspace to a paid plan. Paid plans include more operations, storage, and requests, then bill usage beyond those amounts. Compute memory, CPU, and bandwidth are billed per use on paid plans, and a spend limit can cap the charge. The [pricing page](https://www.prisma.io/pricing) has the rates. ## 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: The prompt uses npm and Node.js. On Bun, replace `npm create prisma@latest --` with `bun create prisma@latest`, `npx` with `bunx`, and `npm run` with `bun run`. ```text Create a new Hono API composed with Prisma Composer and Prisma ORM, run it locally, and deploy it to Prisma Compute. Check the versions first: `node --version` must print 22.18 or newer (on the 24 line, 24.11 or newer). If you use npm, `npm --version` must print 11.6.0 or newer; Node.js 22 comes with npm 10, so if npm is older, run `npm install --global npm@11` before step 1. 1. Scaffold: `npm create prisma@latest -- my-app --template hono --provider postgres --yes`. Then run `npx prisma@latest init` in `my-app` to confirm the Prisma agent skills the scaffold installed are 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 start `npx prisma dev module.ts` in the background and wait until it prints the local URL. 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 with curl that the local URL's /users endpoint returns the seeded users, then stop `dev`. 4. Deploy: check `npx prisma auth whoami`; if I am not signed in, stop and ask me to run `npx prisma auth login` (it opens a browser). The scaffold already wrote the baseline migration under `migrations/app/`; note its directory name, which ends in `_init`. The `composer` section of the scaffold's `prisma.config.ts` already sets the deploy region, so do not add one. Then run `npx prisma 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 contract emit`, add `"role"` to the typed select and the returned object in `src/prisma/users.ts`, and plan the migration with `npx prisma migration plan --name add-user-role --from `. Then run `npm run build` and `npx prisma 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 ORM wired in: #### bun ```bash bun create prisma@latest my-app --template hono --provider postgres --no-deploy ``` #### pnpm ```bash pnpm create prisma@latest my-app --template hono --provider postgres --no-deploy ``` #### yarn ```bash yarn create prisma@latest my-app --template hono --provider postgres --no-deploy ``` #### npm ```bash npm create prisma@latest -- my-app --template hono --provider postgres --no-deploy ``` Answer the prompts for contract authoring style, package manager, and agent skills, or pass the `--authoring`, `--package-manager`, and `--skills` flags to skip them (see the [create-prisma reference](https://www.prisma.io/docs/prisma-orm/create-prisma); Deno projects cannot deploy to Prisma Compute yet, so this tutorial uses Node.js or Bun). 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 ran it already, so on a fresh project `init` confirms the setup and reports each step as already done: the [Prisma agent skills](https://www.prisma.io/docs/ai/tools/skills) that ship inside the Prisma packages are synced, and `package.json` has a `postinstall` hook (`prisma skills sync || exit 0`) that resyncs them on every install, plus a `skills:sync` script for refreshing them by hand. Running `init` again is what 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, and `prisma.config.ts` holds the deploy config. `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" }), }); ``` `prisma.config.ts` is this project's Prisma config: the Prisma CLI reads it, and your app never imports it. Its `orm` section points Prisma ORM at your contract and database, its `skills` section lists the agents you chose at the prompt, and the deploy config is its `composer` section: the extensions that deploy your app and the store that keeps deploy state. The `composer` section already names the region the first deploy needs to create your project, `us-east-1`, so there is nothing to set before you deploy. To deploy somewhere else, change the region here before the first deploy; the region ids are listed under [Limitations](https://www.prisma.io/docs/compute/limitations). The file below is shown for Prisma schema authoring with Claude Code picked for agent skills. Your `skills` list holds the agents you picked, and TypeScript authoring points `contract` at `contract.ts` and adds an `output` path. ```ts title="prisma.config.ts" import { definePrismaConfig } from "prisma/config"; import { defineConfig as ormConfig } from "@prisma/orm-postgres/config"; import { defineConfig as composer } from "@prisma/composer/config"; import { nodeBuild } from "@prisma/composer/node/control"; import { prismaCloud, prismaState } from "@prisma/composer-prisma-cloud/control"; export default definePrismaConfig({ skills: { agents: ["claude"], }, orm: ormConfig({ contract: "./src/prisma/contract.prisma", db: { connection: process.env.DATABASE_URL!, }, }), composer: composer({ extensions: [prismaCloud({ region: "us-east-1" }), nodeBuild()], state: prismaState(), }), }); ``` Notice there is no connection string in the declaration. The database is a declared dependency, typed by your contract, and Composer injects the connection wherever the app runs. The `DATABASE_URL` in the `orm` section is used only by the ORM commands that connect to a database directly, such as the `db:*` scripts at the end of [step 4](#4-run-it-locally-on-prisma-postgres); `prisma dev` and `prisma deploy` do not need it. 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 ORM data model [#3-the-prisma-orm-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 ORM 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 dev module.ts ``` #### pnpm ```bash pnpm run build pnpm prisma dev module.ts ``` #### yarn ```bash yarn build yarn prisma dev module.ts ``` #### npm ```bash npm run build npx prisma 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` keeps running until you press Ctrl-C, so run the curl in a second terminal. `dev` also 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-24 13:51:34.797+00" }, { "id": "2", "email": "bob@prisma.io", "username": "bob", "name": "Bob", "createdAt": "2026-08-24 13:51:34.803+00" }, { "id": "3", "email": "carol@prisma.io", "username": "carol", "name": "Carol", "createdAt": "2026-08-24 13:51:34.804+00" } ] ``` 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 with the CLI, in a project named differently from the module so that it does not collide with the project the deploy in [step 5](#5-deploy-app-and-database-to-prisma-compute) creates: #### bun ```bash bunx prisma auth login bunx prisma project create my-app-local bunx prisma postgres create mydb ``` #### pnpm ```bash pnpm prisma auth login pnpm prisma project create my-app-local pnpm prisma postgres create mydb ``` #### yarn ```bash yarn prisma auth login yarn prisma project create my-app-local yarn prisma postgres create mydb ``` #### npm ```bash npx prisma auth login npx prisma project create my-app-local npx prisma postgres create mydb ``` `postgres create` prints the connection string once; export it as `DATABASE_URL`, and mint another later with `npx prisma 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 auth login ``` #### pnpm ```bash pnpm prisma auth login ``` #### yarn ```bash yarn prisma auth login ``` #### npm ```bash npx prisma auth login ``` Deployed databases evolve through the migrations you commit, so the first migration must create your starting schema. The scaffold already planned it for you as `migrations/app/_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 deploy module.ts ``` #### pnpm ```bash pnpm run build pnpm prisma deploy module.ts ``` #### yarn ```bash yarn build yarn prisma deploy module.ts ``` #### npm ```bash npm run build npx prisma deploy module.ts ``` Composer creates a project named after your module, in the region from the `composer` section of `prisma.config.ts`, provisions the Prisma Postgres database declared in `module.ts`, connects it to the service, and starts the app. There is 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 deploy module.ts --name my-app-tutorial > ``` > > > #### pnpm > ```bash > pnpm prisma deploy module.ts --name my-app-tutorial > ``` > > > #### yarn > ```bash > yarn prisma deploy module.ts --name my-app-tutorial > ``` > > > #### npm > ```bash > npx prisma 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 safe to run more than once: 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" // use prisma-8 model User { id Int @id @default(autoincrement()) email String @unique username String? name String? role String @default("member") posts Post[] createdAt TimestamptzString @default(now()) updatedAt temporal.updatedAtString() } ``` Re-emit the contract, then plan the migration that carries the change, chaining from the baseline migration you committed in [step 5](#5-deploy-app-and-database-to-prisma-compute): #### bun ```bash bunx prisma contract emit bunx prisma migration plan --name add-user-role --from _init ``` #### pnpm ```bash pnpm prisma contract emit pnpm prisma migration plan --name add-user-role --from _init ``` #### yarn ```bash yarn prisma contract emit yarn prisma migration plan --name add-user-role --from _init ``` #### npm ```bash npx prisma contract emit npx prisma migration plan --name add-user-role --from _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 include 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").limit(limit).all(); ``` This is the Prisma ORM 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 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 deploy module.ts ``` #### pnpm ```bash pnpm run build pnpm prisma deploy module.ts ``` #### yarn ```bash yarn build yarn prisma deploy module.ts ``` #### npm ```bash npm run build npx prisma 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-24 18:40:06.375+00" } ] ``` ## 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 project list`): #### bun ```bash bunx prisma project delete --confirm ``` #### pnpm ```bash pnpm prisma project delete --confirm ``` #### yarn ```bash yarn prisma project delete --confirm ``` #### npm ```bash npx prisma project delete --confirm ``` ## 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): how each branch gets its own isolated environment. * [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 and add a deploy workflow so every push deploys, with a preview environment per branch. ## Related pages - [`Choose a Prisma ORM setup path`](https://www.prisma.io/docs/getting-started): Choose the fastest path to try Prisma ORM 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 ORM`](https://www.prisma.io/docs/prisma-orm): Prisma ORM 8 is the current release. - [`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