Prisma
Prisma unlocks a new level of developer experience when working with databases thanks to its intuitive data model, automated migrations, type-safety & auto-completion.
Good to know:
This guide assumes you're using create-turbo or a repository with a similar structure.This guide shows you how to:
- Set up Prisma in a monorepo
- Handle migration and code generation scripts
- Ensure that they're always run whenever
dev
orbuild
is run
If you've already got Prisma set up in your database, you can skip to step 4.
Create your monorepo
If you don't have an existing project, use our quickstart to create a new monorepo.
Add a new database
package
Create a new folder called database
inside packages with a package.json
inside:
Run your package manager's install step to install the new dependencies.
Run prisma init
cd
into packages/database
:
Run npx prisma init
.
This should create several files inside packages/database
:
schema.prisma
is where your Prisma schema lives. Here, you'll be able to modify the shape of your database..gitignore
adds some ignored files to git.env
lets you manually specify yourDATABASE_URL
for prisma.
At this point, you should refer to the Prisma docs for connecting your database to Prisma.
Once you've got a database connected and have a few data tables to work with, you can move on.
Create scripts
Let's add some scripts to the package.json
inside packages/database
:
Let's also add these scripts to turbo.json
in the root:
Now, run turbo db:push db:generate
from the root of our repository to automatically migrate our database and generate our type-safe Prisma client.
Use the --skip-generate
flag on db:push
to ensure it doesn't automatically
run prisma generate
after migrating the database. This ends up being faster
when using Turborepo because it automatically parallelizes the tasks.
Exporting your client
Next, export the @prisma/client
so it can used in your applications. Let's add an index.ts
file to packages/database
:
Following the Just-in-Time packaging pattern, you'll also create an entrypoint to the package inside packages/database/package.json
.
Note that you're using the Just-in-Time Package pattern here, which assumes your application can consume TypeScript directly. You may need to adjust to a different strategy as if needed.
Importing database
Import the database package into one of our apps.
Let's say you have an app at apps/web
. Add the dependency to apps/web/package.json
:
Run your package manager's install command.
You can now import PrismaClient
from database
anywhere in your app:
Figuring out the scripts
You now have a reusable @repo/db
package that you can import into any of your applications and a turbo db:push
script to push schema changes
However, your db:generate
scripts aren't optimized yet. They provide crucial code to our dev
and build
tasks. If a new developer runs turbo dev
on an application without running db:generate
first, they'll get errors.
So, let's make sure that db:generate
is always run before you run dev
:
Check out the section on running tasks to learn more about the ^db:generate
syntax.
Caching the results of prisma generate
prisma generate
outputs files to the filesystem, usually inside node_modules
. In theory, it should be possible to cache the output of prisma generate
with Turborepo to save a few seconds.
However, Prisma behaves differently with different package managers. This can lead to unpredictable results, which might lead to broken deployments in some situations. Instead of documenting the intricacies of each approach, we recommend not caching the results of prisma generate
. Since prisma generate
usually only takes 5-6 seconds, and tends not to take longer with larger schema
files, this seems like a fine trade-off.
You may also wish to experiment with caching the generated files in a way that satisfies the constraints for your repository.
Going to production
Now that you've made it this far, you're ready to deploy your application. Depending on where your database lives, you'll want to design your deployment pipeline according to the documentation for your database's setup.
There are many factors to take into consideration from this point on, so we can't provide a one-size-fits-all solution. You likely want to visit the documentation for your database and its deployment platform to learn more.
Was this helpful?