# Compare Drizzle and Prisma for a Next.js Project

Yes. An agent ports your Next.js app's queries between Drizzle and Prisma in a sandbox, checks both return the same data, times them and writes up the difference.

[Run this on Rush](https://cloud.getrush.ai/run/compare-libraries/nextjs/).

## What the agent does

The agent clones the repository into its own sandbox and starts with what the queries look like today. In a Next.js app like nextjs/saas-starter, `package.json` has Next.js `15.6.0-canary.59`, `drizzle-orm` `^0.43.1` with `drizzle-kit` and the `postgres` driver, and a `pnpm-lock.yaml`. The data layer is small: `lib/db/schema.ts` defines five tables with `pgTable` (`users`, `teams`, `team_members`, `activity_logs`, `invitations`), `lib/db/drizzle.ts` opens one client from `POSTGRES_URL`, and `lib/db/queries.ts` holds six exported functions, from `getUser` and `getUserWithTeam` to `getTeamForUser`, which uses Drizzle's relational `db.query.teamMembers.findFirst` with three levels of `with` to load a team and its members. Server actions in `app/(login)/actions.ts` also call `db.insert` and `db.update` directly.

Since this app already uses Drizzle, the Drizzle branch is the baseline as it stands and the work is the Prisma branch. The agent runs `prisma db pull` against the migrated database to get a `schema.prisma` that matches `lib/db/migrations/0000_soft_the_anarchist.sql`, then fixes what introspection gets wrong (relation names, `@updatedAt`, the `deleted_at` soft delete on `users`). It rewrites the team and user queries in `lib/db/queries.ts` with Prisma Client, keeping each function's name and return shape, so the pages and route handlers under `app/` that import them, `app/api/user/route.ts` and `app/api/team/route.ts` among them, do not change. `getTeamForUser` becomes a `findFirst` with nested `include`, and the agent checks whether `select` keeps the member's `id`, `name` and `email` and nothing else, as the Drizzle `columns` did.

The repository has no tests and no CI, so the agent writes the check itself. It runs `pnpm db:migrate` and `pnpm db:seed` (`lib/db/seed.ts`) against a Postgres it starts in the sandbox, then a small script that calls each ported function with the same inputs on both branches and compares the results as JSON. Any difference, such as a `Date` that comes back as a string or a missing field, goes into the report with both outputs. Then it runs `pnpm build` on each branch, since Prisma adds a generate step and a client that Next.js has to bundle for server components.

Last come the measurements: lines changed from `git diff --stat`, the dependencies each branch adds or drops, the size of the `next build` output for the routes that touch the database, cold start for the first query, and a loop that times each function a fixed number of times against the same seeded data. Every figure is printed by a command in the run, and the transcript keeps its output. Both branches stay in the sandbox.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Clone https://github.com/nextjs/saas-starter. Start Postgres in the sandbox, set POSTGRES_URL, run pnpm db:migrate and pnpm db:seed. The current Drizzle code is the baseline branch. On a second throwaway branch, port the team and user queries in lib/db/queries.ts to Prisma: generate schema.prisma with prisma db pull, fix relations and the deleted_at column, and keep every function's name and return shape so the callers in app/ do not change. Write a script that calls each ported function with the same inputs on both branches and diffs the results as JSON. Run pnpm build on both, time each function over the same number of calls, and write comparison.md with the diff size, dependency changes, build result and output size, parity results, timings and the trade-offs you hit. Open no pull request and push nothing."
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is `comparison.md`, attached to the session with a download link that lasts an hour. It opens with a table, Drizzle and Prisma side by side: lines and files changed, dependencies added and removed, whether `pnpm build` passed, the build output for the database routes, and the timings for each query function. The parity section lists each ported function and whether the two branches returned identical JSON for the same input, with both outputs shown wherever they differed.

The trade-offs section covers what the port showed in this codebase rather than in general: how the nested `with` in `getTeamForUser` translated, how each handles the `deleted_at` soft delete, how the generated schema differs from `lib/db/schema.ts`, and what the extra generate step does to `next build` and to deploys. The transcript keeps every command with its output, so each row can be checked.

Before acting on it, a reviewer checks that the parity script covered the inputs that matter (a user with no team, a team with several members), that the timing loop ran against the same data on both branches, and whether the server actions in `app/(login)/actions.ts` would also have to move. A follow-up message to the same session can ask for that wider port or for a pull request from the Prisma branch.

## Run it on every new Drizzle or Prisma major

An ORM comparison ages with each major release on either side. Have a job on your server check the npm versions of `drizzle-orm` and `prisma` and send this request when a major changes, with an `Idempotency-Key` built from the two versions so each pair starts one run.

Give the API key a webhook URL and Rush POSTs `run.completed` with the `session_url` when the run ends. Your server fetches `comparison.md` from the session's artifacts and files it next to the earlier ones, so the decision record shows how the gap moved.

## Why run it on Rush?

This comparison needs a real Postgres, a migrated and seeded schema, two branches with different generated clients and two production builds. In a Rush sandbox the agent sets all of that up on its own machine and throws it away after, and no `node_modules`, Prisma engine or local database lands on your laptop.

The value is in the proof. Parity is shown by a diff of real query results, timings by the loop that produced them, and both are in the run's transcript with their output, so the team argues from evidence instead of blog posts. Several of these can run at once, for different apps or different query modules, up to the key's concurrent run limit.

## Frequently asked questions

### My project has no tests. How does the agent know the port is correct?

It writes a parity script that calls each ported function with the same inputs on both branches against the same seeded database and diffs the JSON. Any mismatch is listed in the report with both outputs. That is a narrower check than a test suite, and the report says which functions and inputs it covered.

### Does it need my database?

No. The agent starts Postgres inside the sandbox, applies the repository's migrations and runs its seed script. Your own databases are never touched.

### Can I compare in the other direction, from Prisma to Drizzle?

Yes. If your app is on Prisma, the prompt keeps Prisma as the baseline and ports the chosen module to Drizzle. The parity script, build and timings work the same way either way.

### Will the result be a pull request?

Not by default. The prompt asks for a report and says to push nothing. If the report convinces you, send the same session a follow-up asking for a pull request from the branch you want; its sandbox still has both branches.
