Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions apps/blog/content/blog/data-migrations-in-prisma-next/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ series: prisma-next
seriesIndex: 5
---

Sooner or later, you need a migration to change data as well as schema. In Prisma Next, that happens inside your migration in TypeScript, with the same query builder you use in your app.
Sooner or later, you need a migration to change data as well as schema. In Prisma Next, that happens inside your migration in TypeScript, with the same [query builder](https://www.prisma.io/docs/orm/next/fundamentals/writing-data) you use in your app.

In the [previous post](https://pris.ly/ts-migrations-pn) we covered how migrations change the database schema: a TypeScript migration file with a list of operations, compiled to JSON, applied by the migration runner. Start there if any of those terms are unfamiliar.
In the [previous post](https://pris.ly/ts-migrations-pn) we covered [how migrations change the database schema](https://www.prisma.io/docs/orm/next/migrations/how-migrations-work): a TypeScript migration file with a list of operations, compiled to JSON, applied by the [migration runner](https://www.prisma.io/docs/orm/next/migrations/applying-a-migration). Start there if any of those terms are unfamiliar.

Take a common example. You've added a `displayName` column to `User` in `contract.prisma` and you want to make it `NOT NULL`. There's a snag: there are already rows in the table, and they don't have a `displayName` yet, so setting the column `NOT NULL` fails, every existing row violates the constraint.
Take a common example. You've added a `displayName` column to `User` in [`contract.prisma`](https://www.prisma.io/docs/orm/next/contract-authoring/the-data-contract) and you want to make it `NOT NULL`. There's a snag: there are already rows in the table, and they don't have a `displayName` yet, so setting the column `NOT NULL` fails, every existing row violates the constraint.

A simple approach to solve this problem is to:

Expand Down Expand Up @@ -76,7 +76,7 @@ People have asked for the obvious fix, being able to use the Prisma client _insi

## In Prisma Next, you write the data step in TypeScript

Here is the same example, written as a Prisma Next migration. The initial file is written for you by `migration plan` when you change your `contract.prisma`. The `dataTransform()` line you'd add by hand:
Here is the same example, written as a Prisma Next migration. The initial file is written for you by [`migration plan`](https://www.prisma.io/docs/orm/next/migrations/generating-a-migration) when you change your `contract.prisma`. The `dataTransform()` line you'd add by hand:

```typescript
// migrations/20260422T0748_add_user_display_name/migration.ts
Expand Down Expand Up @@ -184,7 +184,7 @@ This is what lets a data transformation reference columns the same migration is

## MongoDB gets data transformations too

Here's a `dataTransform` against a Mongo collection, backfilling a `status` field on a `products` collection so it can be made required:
Here's a `dataTransform` against a [Mongo collection](https://www.prisma.io/docs/orm/next/data-modeling/mongodb), backfilling a `status` field on a `products` collection so it can be made required:

```typescript
import { dataTransform } from "@prisma-next/target-mongo/migration";
Expand Down
12 changes: 6 additions & 6 deletions apps/blog/content/blog/mongodb-without-compromise/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ tags:
- "announcement"
---

For the first time, Prisma Next brings the MongoDB-native experience to TypeScript. Type-safe queries, database migrations, polymorphic models, embedded collections and more. Designed in collaboration with the MongoDB DX team.
For the first time, [Prisma Next](https://www.prisma.io/docs/orm/next) brings the MongoDB-native experience to TypeScript. Type-safe queries, database migrations, polymorphic models, embedded collections and more. Designed in collaboration with the MongoDB DX team.

## What MongoDB development looks like today

Expand All @@ -25,7 +25,7 @@ If you've built a MongoDB app with TypeScript recently, you've probably gone thr
- You write a query and the types don't fully connect, so you cast, add guards, or accept a little `any`.
- You need an index, so you drop into the MongoDB shell or a deployment script and hope your database stays in sync with your code.

In Prisma Next, you describe your data model as a contract:
In Prisma Next, you describe your [data model](https://www.prisma.io/docs/orm/next/data-modeling/mongodb) as a contract:

```prisma
model User {
Expand Down Expand Up @@ -97,13 +97,13 @@ const recentPosts = await orm.posts
// recentPosts[0].author.bio -> string | null
```

The `.include('author')` compiles to a `$lookup` pipeline stage. Skip the `.include()` and the author isn't loaded and isn't in the type. Your documents are typed all the way down, no matter how far you nest.
The [`.include('author')`](https://www.prisma.io/docs/orm/next/fundamentals/relations-and-joins) compiles to a `$lookup` pipeline stage. Skip the `.include()` and the author isn't loaded and isn't in the type. Your documents are typed all the way down, no matter how far you nest.

## Real migrations for MongoDB

MongoDB is not schema-less. Your deployment has real, persistent, server-side state, and that state directly affects correctness and performance. Yet most tools do not manage it properly.

The `@@index` declarations in the contract above are not just documentation. They are managed by a migration system that versions, diffs, and deploys your database state.
The `@@index` declarations in the contract above are not just documentation. They are managed by a [migration system](https://www.prisma.io/docs/orm/next/migrations/how-migrations-work) that versions, diffs, and deploys your database state.

- **Indexes:** unique, compound, TTL, partial, geospatial, text, and wildcard. If an index is wrong, queries slow down. If a unique constraint is missing, duplicate data can slip in.
- **JSON Schema validators:** document-level validation rules generated from your model definitions. Even writes that bypass the ORM are still validated by the server.
Expand Down Expand Up @@ -165,7 +165,7 @@ Polymorphism connects to migrations too. An index on a variant-specific field, `

## Typed aggregation pipelines

When you need MongoDB's aggregation pipeline for grouping, projecting, or faceting, Prisma Next provides a typed pipeline builder:
When you need MongoDB's aggregation pipeline for grouping, projecting, or faceting, Prisma Next provides a [typed pipeline builder](https://www.prisma.io/docs/orm/next/fundamentals/advanced-queries):

```typescript
const { pipeline, runtime } = orm;
Expand Down Expand Up @@ -198,7 +198,7 @@ Field references like `f.authorId` and `f.createdAt` check against your contract
}))
```

When the pipeline builder doesn't cover what you need, you can drop to raw MongoDB commands:
When the pipeline builder doesn't cover what you need, you can drop to [raw MongoDB commands](https://www.prisma.io/docs/orm/next/reference/raw-queries):

```typescript
const raw = orm.raw.collection('posts');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,28 @@ seriesIndex: 6

If you've ever wanted to integrate your tool, your database, or your library with Prisma, or you tried in Prisma 6 or 7 and gave up, this post is for you. Read the [Prisma Next Early Access announcement](https://www.prisma.io/blog/prisma-next-early-access-write-your-contract-prompt-your-agent-ship-your-app) for the full launch story.

Prisma Next has a deliberately tiny core that knows nothing about any specific database. Postgres support is an extension. Vector search is an extension. JSON-with-schema is an extension. Whatever Prisma Next can do, it does because someone wrote it using the same components that are available to you.
[Prisma Next](https://www.prisma.io/docs/orm/next) has a deliberately tiny core that knows nothing about any specific database. Postgres support is an extension. Vector search is an extension. JSON-with-schema is an extension. Whatever Prisma Next can do, it does because someone wrote it using the same components that are available to you.

The API surface is real, the same shape we used to build Postgres support ourselves, and ready to build against today.

## Postgres is an extension

The Prisma Next framework knows about contracts, plans, query lifecycle, and the policies that gate execution. It does _not_ know what Postgres, SQL, Mongo, vectors, or any column type other than `unknown` are.
The Prisma Next framework knows about [contracts](https://www.prisma.io/docs/orm/next/contract-authoring/the-data-contract), plans, query lifecycle, and the policies that gate execution. It does _not_ know what Postgres, SQL, Mongo, vectors, or any column type other than `unknown` are.

Every database we support and every native feature you've used in Prisma Next was added by an extension package on a public service provider interface (SPI). The Postgres target, the SQL family (its contract shape, operations, and lanes), the Postgres adapter and driver, the pgvector vector type and its similarity operators, and the arktype-JSON codec are all extensions.

There is no "core API" and "plugin API." There is one SPI, used by the team building Prisma Next and by anyone shipping a package today. Anything we build, you can build alongside us or in place of.

## What an extension can ship

An extension is a normal npm package: `@yourname/prisma-next-extension-foo`. Your users `pnpm add` it, add one line to `prisma-next.config.ts`, and your additions show up in their contract, their queries, and (if you ship migrations) their migration plans.
An extension is a normal npm package: `@yourname/prisma-next-extension-foo`. Your users `pnpm add` it, [add one line to `prisma-next.config.ts`](https://www.prisma.io/docs/orm/next/extensions/using-extensions), and your additions show up in their contract, their queries, and (if you ship migrations) their migration plans.

An extension can include any subset of four layers, in any combination:

- **Contract layer**: column types, field builders, index types, and authoring constructs that show up in `contract.ts` and `contract.json` with your namespace and your validation rules. This is how pgvector adds dimensioned vector columns and how ParadeDB adds typed BM25 indexes
- **Query layer**: typed methods on the query builder. Users discover them through autocomplete; they compile to SQL via lowerers you provide. This is how pgvector adds `cosineDistance` on vector columns
- **Runtime layer**: codecs that translate between the database wire format and your TypeScript types. Codecs can be synchronous (pgvector vectors decode to `number[]`) or asynchronous (encryption codecs decrypt on read with key material from an external service). Runtime middleware is also part of this slice, covering observability, audit, and policy interception around every query
- **Migration layer**: custom DDL and data operations with pre/post checks and idempotency declarations, integrated into the migration planner. ParadeDB's planned BM25 index ops land here, and so does anything else that needs to participate in the migration graph rather than ship as a one-off script
- **Runtime layer**: codecs that translate between the database wire format and your TypeScript types. Codecs can be synchronous (pgvector vectors decode to `number[]`) or asynchronous (encryption codecs decrypt on read with key material from an external service). [Runtime middleware](https://www.prisma.io/docs/orm/next/middleware/how-middleware-works) is also part of this slice, covering observability, audit, and policy interception around every query
- **Migration layer**: custom DDL and data operations with pre/post checks and idempotency declarations, integrated into the migration planner. ParadeDB's planned BM25 index ops land here, and so does anything else that needs to participate in [the migration graph](https://www.prisma.io/docs/orm/next/migrations/the-migration-graph) rather than ship as a one-off script

Pick the layers you need. A useful extension can be one layer (a single codec, a single index type) or all four for a full vertical slice.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Today, **Prisma Next is open for Early Access for Postgres and [MongoDB](https:/

If you've ever picked up a new framework, you know how long it takes to climb a steep learning curve. You read the docs, build a toy project and make mistakes the docs warned you about. It takes weeks to absorb the framework's idioms until you're confident enough to actually build.

One command scaffolds a new project with Prisma Next, including a family of skills which make your agent an instant expert.
One command scaffolds a new project with Prisma Next, including a [family of skills](https://www.prisma.io/docs/ai/tools/skills) which make your agent an instant expert.

```bash
npm create prisma@next
Expand All @@ -61,7 +61,7 @@ model Book {
}
```

This is the contract between your application and your database. The models are what your application depends on, and your database promises to store them in the shapes described in the contract.
This is [the contract](https://www.prisma.io/docs/orm/next/contract-authoring/the-data-contract) between your application and your database. The models are what your application depends on, and your database promises to store them in the shapes described in the contract.

It's easy to read, easy to update, and it's the single source of truth for everything in Prisma Next. Queries are type-checked against it, autocomplete reads from it, and when you change it, Prisma Next plans the migrations to match, so your database continues to satisfy the contract.

Expand All @@ -84,7 +84,7 @@ Considering the book table in the contract above, you can ask the agent for a fe
after={contractAfterAuthor}
/>

Then, when you ask the agent to write a query, it iterates inside its own tool calls until the query type-checks, or until it resolves any errors. Here's what that looks like in practice:
Then, when you ask the agent to [write a query](https://www.prisma.io/docs/orm/next/fundamentals/reading-data), it iterates inside its own tool calls until the query type-checks, or until it resolves any errors. Here's what that looks like in practice:

<AgentPrompt
prompt="query all the books from the last week and also include the author"
Expand All @@ -99,7 +99,7 @@ You can be confident that if the agent's query typechecks, it matches the contra

## Never write a migration again

If you've ever deployed an app, you've worked with migrations. Migrations are _one of the most painful parts_ of working with a database.
If you've ever deployed an app, you've worked with [migrations](https://www.prisma.io/docs/orm/next/migrations/how-migrations-work). Migrations are _one of the most painful parts_ of working with a database.

You spend time getting the syntax right. Then you spend more time debugging when things go sideways. And _when_ - not if - a migration breaks during deployment, you spend even more time fixing it while your production app is down.

Expand Down Expand Up @@ -194,7 +194,7 @@ If you find a bug, or something you feel is missing, ask your agent to tell us a

Prisma Next brings **Prisma's world-class DX to your agent**, so you can focus on building your app. Stay hands-on, let your agent take over, or switch mid-flow. With Prisma Next, you can delegate with confidence.

To try it today in a fresh project, run:
To [try it today](https://www.prisma.io/docs/next/quickstart/postgresql) in a fresh project, run:

```bash
npm create prisma@next
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ seriesIndex: 9

Every ORM does work on every query: it turns your query into SQL, sends it, and turns the rows that come back into objects. That work has a cost, and in Prisma 7 it sits deep in the architecture, so reducing it meant rebuilding the layers underneath.

That rebuild is [Prisma Next](https://pris.ly/pn-series), the new foundation for Prisma ORM. It's written in TypeScript end to end and runs on a much lighter core, while keeping the same model-first, type-safe workflow you already use.
That rebuild is [Prisma Next](https://pris.ly/pn-series), the new foundation for Prisma ORM. It's written in TypeScript end to end and runs on a much lighter core, while keeping the same [model-first, type-safe workflow](https://www.prisma.io/docs/orm/next) you already use.

To see where it stands, we ran the same Postgres workload through three setups: Prisma 7, Prisma Next, and the raw `pg` driver. We pushed traffic up until each one reached its limit.

Expand Down Expand Up @@ -97,7 +97,7 @@ We've shared [our benchmark repo](https://pris.ly/pn-benchmarks), so you can run

## Try Prisma Next today

There are two ways to get started. To spin up a complete template app, scaffold one with:
There are two ways to [get started](https://www.prisma.io/docs/next/quickstart/postgresql). To spin up a complete template app, scaffold one with:

```shell
bunx create-prisma@next
Expand Down
Loading
Loading