# Prisma 2 Preview: Type-safe Database Access & Declarative Migrations URL: https://www.prisma.io/blog/announcing-prisma-2-zq1s745db8i5 Published: 2019-06-18 Authors: Nikolas Burk Description: Prisma 2 Preview introduced a type-safe database client and declarative migrations to modernize database workflows for application developers. > Blog posts describe Prisma as it was on the date shown and are not kept current. Before implementing from a post, check the documentation index at https://www.prisma.io/docs/llms.txt and the changelog at https://www.prisma.io/changelog.md. > For an index of every published post, fetch https://www.prisma.io/blog/llms.txt. We are excited to share the Prisma 2 Preview today. It features a **type-safe database client** ([Photon](https://github.com/prisma/orm/releases/tag/2.0.0-preview020)) and a **declarative migration system** ([Lift](https://github.com/prisma/orm/releases/tag/2.0.0-preview020)). Help us improve Prisma 2 by trying it out and sharing your feedback! This is an early Preview of Prisma 2. Current [limitations](https://github.com/prisma/prisma2/blob/master/docs/limitations.md) include missing features, limited performance and stability issues. We will address all these limitations before issuing a stable release later this year. ## TLDR [#tldr] Today we're launching a first Preview of Prisma 2. It consists of two major tools that simplify and modernize database workflows: * [Photon](https://github.com/prisma/orm/releases/tag/2.0.0-preview020): A type-safe and auto-generated databases client (*think: ORM*) * [Lift](https://github.com/prisma/orm/releases/tag/2.0.0-preview020): Declarative data modeling and database migrations Photon and Lift can be used *standalone* or *together* in your application. Prisma 2 will be running in Preview for a few months. Please try it out and share your feedback! *** ## Contents [#contents] * [Database workflows in 2019 are antiquated](#database-workflows-in-2019-are-antiquated) * [Prisma 2: Next-generation database tooling](#prisma-2-next-generation-database-tooling) * [Getting started with Prisma 2](#getting-started-with-prisma-2) * [Why Prisma is not like existing DB tools / ORMs](#why-prisma-is-not-like-existing-db-tools--orms) * [What's new in Prisma 2?](#whats-new-in-prisma-2) * [Stabilize Prisma 2 & avoid future breaking changes](#stabilize-prisma-2--avoid-future-breaking-changes) * [Want a certain feature? Share your feedback!](#want-a-certain-feature-share-your-feedback) * [See you at Prisma Day](#see-you-at-prisma-day) ## Database workflows in 2019 are antiquated [#database-workflows-in-2019-are-antiquated] In recent years, many areas of application development have been modernized to fit the new requirements brought by the era of digitization: * **Frontend** web applications are typically powered by declarative abstractions of the DOM (React, Vue, ...) instead of using static HTML and jQuery. * **Backend** developers benefit from modern languages and runtimes such as Node.js, Go or Elixir to make the right tradeoffs for their use case. * **Compute** used to be provisioned in private data centers. Today, most workloads can run in containers or serverless in public clouds. * **Storage** solutions are transitioning from being self-hosted to managed services like RDS or Azure Storage. But what about the **database workflows** developers are dealing with every day? What's the next-generation tooling for **accessing databases** from within an application or for performing **schema migrations**? ![Confusion with data management](https://www.prisma.io/blog/announcing-prisma-2-zq1s745db8i5/imgs/gqbGz7b.png) For database access, developers can use traditional ORMs (e.g. [Sequelize](http://docs.sequelizejs.com) for Node.js or [GORM](https://github.com/jinzhu/gorm) for Go). While often beneficial to get a project off the ground, these aren't a good longterm fit as project complexity quickly outgrows the capabilities of traditional ORMs. The tooling and best practices for schema migrations are even more fragmented and organizations tend to develop their own tools and processes for migrating database schemas. ## Prisma 2: Next-generation database tooling [#prisma-2-next-generation-database-tooling] After helping large companies and individual developers solving their data access challenges for the last three years, we are proud to release a set of tools that help developers work with databases in modern development stacks. Prisma 2 encompasses two standalone tools to tackle the problems of data access and migrations: * [**Photon**](https://github.com/prisma/orm/releases/tag/2.0.0-preview020): A type-safe database client for more efficient and safe database access * [**Lift**](https://github.com/prisma/orm/releases/tag/2.0.0-preview020): A modern and declarative migration system with custom workflows Let's take a look at Photon and Lift in more detail. ### Photon – A type-safe database client to replace traditional ORMs [#photon--a-type-safe-database-client-to-replace-traditional-orms] ![Photon.js diagram](https://www.prisma.io/blog/announcing-prisma-2-zq1s745db8i5/imgs/AG34kGB.png) Photon is a type-safe database client that's auto-generated based on the Prisma data model (which is a representation of your database schema). It provides a powerful and lightweight layer of mapping code you can use to talk to a database in your application. It has a modern and ergonomic data access API that's tailored to the needs of application developers. You can explore the Photon API on the [Photon site](https://github.com/prisma/orm/releases/tag/2.0.0-preview020). ### Lift – Declarative data modeling & migrations [#lift--declarative-data-modeling--migrations] ![Lift demo](https://www.prisma.io/blog/announcing-prisma-2-zq1s745db8i5/imgs/bFUA7LC.png) Lift is based on Prisma's declarative [data model definition](https://github.com/prisma/prisma2/blob/master/docs/data-modeling.md) which codifies your database schema(s). To migrate your database, you adjust the data model and "apply" the changes using the Lift CLI. Every migration is represented via an explicit series of steps so you can keep a migration history throughout the lifetime of your project and easily can go back and forth between migrations. Migrations can also be exteneded with before/after hooks. ### Better together: Seamless integration of Photon and Lift workflows [#better-together-seamless-integration-of-photon-and-lift-workflows] Both Photon and Lift can be used standalone in your applications, whether greenfield or brownfield. However, they're both seamlessly integrated through the [Prisma CLI](https://github.com/prisma/prisma2/blob/master/docs/prisma-2-cli.md) and work great together. A shared foundation for both tools is the [data model definition](https://github.com/prisma/prisma2/blob/master/docs/data-modeling.md#data-model-definition) which has two responsibilities: * For **Photon**, it provides the *models* for the generated database client (CRUD API) * For **Lift**, it describes the schema of the underlying database(s) The data model is at the heart of your Photon and Lift workflows. It serves as an *intermediate abstraction* between your database schema and the programmatic API you use to talk to your database. *** ## Getting started with Prisma 2 [#getting-started-with-prisma-2] **UPDATE (January 2020)**: This section of the blog post is outdated. The setup instructions for Prisma 2 have changed since the blog post was first published. You can [**get started**](https://github.com/prisma/prisma2/blob/master/docs/getting-started/README.md) in the official Prisma 2 docs on GitHub. ### Expand to view the outdated setup instructions. ### 1. Install the Prisma 2 CLI [#1-install-the-prisma-2-cli] You can install the [Prisma 2 CLI](https://github.com/prisma/prisma2/blob/master/docs/prisma-2-cli.md) using npm or Yarn: ```shell npm install -g prisma2 ``` ```shell yarn global add prisma2 ``` ### 2. Run the interactive `prisma2 init` flow & select boilerplate [#2-run-the-interactive-prisma2-init-flow--select-boilerplate] Run the following command to get started: ```shell prisma2 init hello-prisma2 ``` Select the following in the interactive prompts: 1. Select **SQLite** 2. Check both options, **Photon** and **Lift** 3. Select **TypeScript** 4. Select **From scratch** Once terminated, the `init` command created an initial project setup for you. Move into the `hello-prisma2` directory and install the Node dependencies. ```shell cd hello-prisma2 npm install ``` ### 3. Migrate your database with Lift [#3-migrate-your-database-with-lift] Migrating your database with Lift follows a 2-step process: 1. *Save* a new migration (migrations are represented as directories on the file system) 2. *Run* the migration (to actually migrate the schema of the underlying database) In CLI commands, these steps can be performed as follows (*the CLI steps are in the process of being updated to match*): ```shell prisma2 lift save --name 'init' prisma2 lift up ``` ### 4. Access your database with Photon [#4-access-your-database-with-photon] The script in `src/script.ts` contains some sample API calls, e.g.: ```ts const allPosts = await photon.posts.findMany({ where: { published: true }, }) const newPost = await photon.posts.create({ data: { title: 'Join the Prisma Slack community', content: 'http://slack.prisma.io', published: false, author: { connect: { email: 'alice@prisma.io' }, }, }, }) const postsByUser = await photon.users .findOne({ where: { email: 'alice@prisma.io' }}) .posts() } ``` You can seed your database using the seed script from `package.json`: ```shell npm run seed ``` You can execute the script with the following command: ```shell npm run start ``` ### 5. Build an app [#5-build-an-app] With Photon being connected to your database, you can now start building your application. In the [`photonjs`](https://github.com/prisma/photonjs/) repository, you can find reference examples for the following use cases (for JavaScript and TypeScript): * [GraphQL example](https://github.com/prisma/photonjs/tree/master/examples/typescript/graphql) * [REST example](https://github.com/prisma/photonjs/tree/master/examples/typescript/rest-express) * [gRPC example](https://github.com/prisma/photonjs/tree/master/examples/typescript/grpc) *** ## Why Prisma is not like existing DB tools / ORMs [#why-prisma-is-not-like-existing-db-tools--orms] Developers typically use a mix of existing and custom/handwritten database tools for their every day database worfklows. Prisma unifies the main database workflows in a coherent ecosystem to make developers more productive. ### Prisma uses a declarative data model [#prisma-uses-a-declarative-data-model] With Prisma, you define your models using a declarative and human-friendly [data modeling syntax](https://github.com/prisma/prisma2/blob/master/docs/data-modeling.md). The defined models get mapped to the underlying database(s) and at the same time provide the foundation for Photon's generated data access API. Another major benefit of this approach is that the data model definition can be checked into version control so the entire team is always aware of the models the application is based on. ### Photon is a type-safe and auto-generated database client [#photon-is-a-type-safe-and-auto-generated-database-client] Traditional ORMs often don't cater to the complex requirements of large applications, but a data mapping layer is still needed. A typical solution is to handroll a custom data access layer for the application models. Photon is auto-generated code that replaces the manual data access layer you'd write for your application anyways. Having it auto-generated ensures a consistent API, reduces human error and saves a lot of time otherwise spent writing CRUD boilerplate. Photon provides a fully type-safe API (even for JavaScript). This API can be used as foundation to build more advanced ORM patterns (repository, active record, entities, ...). ### Focus on developer experience & ergonomics [#focus-on-developer-experience--ergonomics] While most traditional ORMs try to simply abstract SQL into a programming language, Photon's data access API is designed with the developer in mind. Especially when working with *relations*, Photon's API is a lot more developer-friendly compared to traditional ORMs. JOINs and atomic transactions are abstracted elegantly into nested API calls. Here are a few examples: ```ts // Retrieve the posts of a user const postsByUser: Post[] = await photon.users.findOne({ where: { email: 'ada@prisma.io' } }).posts() // Retrieve the categories of a post const categoriesOfPost: Category[] = await photon.posts.findOne({ where: { id: 1 } }).categories() ``` ```ts // The returned post objects will only have the `id` and // `author` property which carries the respective user object const allPosts: Post[] = await photon.posts.findMany({ select: { id: true, author: true }, }) // The returned posts objects will have all scalar fields of the `Post` model and additionally all the categories for each post const allPosts: Post[] = await photon.posts.findMany({ include: { categories: true }, }) ``` ```ts // Retrieve all posts of a particular user // that start with "Hello" const posts: Post[] = await photon.users .findOne({ where: { email: 'ada@prisma.io' }, }) .posts({ where: { title: { startsWith: 'Hello' }, }, }) ``` ```ts // Create a new user with two posts in a // single transaction const newUser: User = await photon.users.create({ data: { email: 'alice@prisma.io', posts: { create: [{ title: 'Join the Prisma Slack on https://slack.prisma.io' }, { title: 'Follow @prisma on Twitter' }], }, }, }) // Change the author of a post in a single transaction const updatedPost: Post = await photon.posts.update({ where: { id: 5424 }, data: { author: { connect: { email: 'alice@prisma.io' }, }, }, }) ``` Learn more about Photon's relations API in the [docs](https://github.com/prisma/prisma2/blob/master/docs/relations.md#relations-in-the-generated-Photon-API). ### Safe & resilient migrations for simple and complex use cases with Lift [#safe--resilient-migrations-for-simple-and-complex-use-cases-with-lift] Migrating database schemas can be an incredibly time-consuming and frustrating experience. Lift empowers developers with a simple model for migrations that's powerful enough for even the most complex use cases. In the vast majority of cases, developers can simple adjust their declarative [data model definition](https://github.com/prisma/prisma2/blob/master/docs/data-modeling.md) to represent the desired database structure, then *save* and *run* the migration: ```shell prisma2 lift save # stores a new migration folder on the file system prisma2 lift up # applies the migration from the previous step ``` Whenever this workflow doesn't match your needs, you can extend it using "before/after"-hooks to run custom code before or after the migration is performed. The migration folders (and the migrations history table in the database) let developers further do easy rollbacks of migration. Lift is also designed to work seamlessly in CI/CD environments. In the future, Lift will enable *immutable schema deploys* (inspired by ZEIT's [immutable deploys](https://zeit.co/docs/v2/deployments/concepts/immutability/)). ## What's new in Prisma 2? [#whats-new-in-prisma-2] Prisma 2 not only splits up Prisma's main workflows into standalone tools, it also introduces fundamental improvements to each tool itself and provides a robust core for future development. ### Improved datamodel syntax & project definition [#improved-datamodel-syntax--project-definition] In Prisma 1, there were two files that were required for every Prisma project: * `prisma.yml`: Root configuration file for the project * `datamodel.prisma`: Abstracts the database and provides foundation for generated Prisma client API In Prisma 2, the configuration options and the data model have been merged into a single [**Prisma schema file**](https://github.com/prisma/prisma2/blob/master/docs/prisma-schema-file.md), typically called `schema.prisma`. Developers define a data model and specify how to connect to various *data sources* as well as target *code generators* (such as the [`photonjs`](https://github.com/prisma/prisma2/blob/master/docs/core/generators/photonjs.md)-generator) in the schema file. A simple example of a new project definition could look as follows: ```prisma datasource pg { provider = "postgresql" url = env("POSTGRES_URL") } generator js { provider = "photonjs" } model User { id Int @id email String @unique name String posts Post[] } model Post { id Int @id createdAt DateTime @default(now()) updatedAt DateTime @updatedAt draft Boolean @default(true) author User } ``` Prisma 2 also comes with a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) that provides **auto-formatting** and **syntax highlighting** (and more features like auto-completion, jump-to-definition and linting coming soon) for the data modeling syntax! Learn more about the improved data modeling syntax in the [docs](https://github.com/prisma/prisma2/blob/master/docs/data-modeling.md). > **Note for Prisma 1 users**: The new data model syntax is heavily inspired by SDL. It has been optimized to describe *database schemas*, but in most use cases using it will feel very familiar to defining a Prisma 1 datamodel. Learn more in the [spec](https://github.com/prisma/specs/tree/master/prisma-schema). ### Improved data access API & type-safe field selection in Photon [#improved-data-access-api--type-safe-field-selection-in-photon] Photon provides a powerful data access API with some slight changes and improvements compared to the Prisma client API. Find the full API documentation [here](https://github.com/prisma/prisma2/blob/master/docs/photon/api.md). #### Unifying access to CRUD operations [#unifying-access-to-crud-operations] The CRUD operations are *unified* across models and are accessible via a property on your Photon instance, e.g. for the model `User` you can access the operations to read and write data as follows: ```ts const newUser = await photon.users.create({ data: { name: 'Alice', }, }) const allUsers = await photon.users.findMany() const oneUser = await photon.users.findOne({ where: { id: 1 }, }) ``` ```ts const newUser = await prisma.createUser({ name: 'Alice', }) const allUsers = await prisma.users()() const oneUser = await prisma.user({ id: 1, }) ``` Note that the name of the `users` property is generated using the [`pluralize`](https://github.com/blakeembrey/pluralize) package. You can find the API reference for Photon.js in the [docs](https://github.com/prisma/prisma2/blob/master/docs/photon/api.md). #### Type-safe field selection via `select` and `include` [#type-safe-field-selection-via-select-and-include] A brand new feature in Photon's data access API is the ability to precisely specify the fields that should be returned from an API operation in a type-safe way. This can be done via either of two options that can be passed into *any* CRUD API call: * `select`: Only returns the fields that are explicitly specified ([*select exclusively*](https://github.com/prisma/prisma2/blob/master/docs/photon/api.md#select-exclusively-via-select)) * `include`: Includes extra fields, e.g. relations or lazy properties ([*include additionally*](https://github.com/prisma/prisma2/blob/master/docs/photon/api.md#include-additionally-via-include)) > Note that `include` is not **yet** part of the Photon.js API but will be **very soon**! Assume you your Photon API was generated from the data model [above](#improved-datamodel-syntax--project-definition), here is an example for using `select` and `include`: ```ts // Default selection const oneUser = await photon.users.findOne({ where: { id: 1 }, }) // oneUser = { id: 1, name: "Alice", email: "alice@prisma.io" } // Select exclusively const oneUser = await photon.users.findOne({ where: { id: 1 }, select: { email: true }, }) // oneUser = { email: "alice@prisma.io" } // Include additionally const oneUser = await photon.users.findOne({ where: { id: 1 }, include: { posts: true }, }) // oneUser = { id: 1, name: "Alice", email: "alice@prisma.io", posts: [ ... ] } ``` This code snippet only highlights `select` and `include` for `findOne`, but you can provide these options to any other CRUD operation: `findMany`, `create`, `update` and `delete`. You can learn more about the field selection API of Photon.js in the [docs](https://github.com/prisma/prisma2/blob/master/docs/photon/api.md#field-selection). ### Making the Prisma server optional [#making-the-prisma-server-optional] The Prisma server that was required as a database proxy in Prisma 1 is now optional. This is due to a fundamental architecture change: the query and migration engines that previously ran inside the Prisma server can now run as plain binaries alongside your application on the same host. ![Prisma client](https://www.prisma.io/blog/announcing-prisma-2-zq1s745db8i5/imgs/l1Jg54Y.png) ### The Prisma core is rewritten in Rust [#the-prisma-core-is-rewritten-in-rust] Prisma 1 is implemented in Scala which means it needs to run in the JVM. To reduce the overhead of running Prisma, we decided to rewrite it in Rust. Benefits of Rust include a significantly lower memory footprint, better performance and no more need to deploy, monitor and maintain an extra server to run Prisma 2. Rust has shown to be the perfect language for Prisma, allowing us to write safe and extremely performant code. ## Stabilize Prisma 2 & avoid future breaking changes [#stabilize-prisma-2--avoid-future-breaking-changes] While Prisma 2 introduces a number of breaking changes, we strongly believe that those also come with fundamental improvements and are necessary to fulfill our vision of building a modern data layer for simple and complex applications. We are investing a lot into the Preview period to ensure we're building upon a stable foundation in the future. During the Preview, there might still be breaking changes. After the GA release, we commit to providing a stable, non-breaking API. Please help us by reporting any issues you encounter and asking questions that are not addressed in the [docs](https://github.com/prisma/prisma2). We're further planning a number of blog posts that will dive deeper into specific parts of Prisma 2. This includes topics like the Rust rerwrite, how Lift works under the hood as well as articles that motivate many of our technical decisions and describe our core design principles. *** ## Want a certain feature? Share your feedback! [#want-a-certain-feature-share-your-feedback] We are super excited about the state of Prisma 2, but we don't want to stop here. We know that some decisions we made might be controversial, so if you have strong opinions [**please join the discussion**](https://slack.prisma.io) to share your thoughts, ideas and feedback! If you want to **make an impact and help shaping what Prisma 2 will look like** in the end, now is the right time to chime in! Leave your feedback in our [#prisma2-preview channel](https://prisma.slack.com/messages/CKQTGR6T0/) on Slack or by opening an issue in the [`lift`](https://github.com/prisma/lift) or [`photonjs`](https://github.com/prisma/photonjs) repos. *** ## See you at Prisma Day [#see-you-at-prisma-day] The Prisma 2 Preview is not the only exciting thing happening this week. We are psyched for three days of conferences coming up: * [Prisma Day](https://www.prisma.io/day) (**SOLD OUT**) * [GraphQL Conf](https://www.graphqlconf.org/) (**Late bird tickets still available**) We are especially looking forward to welcoming the Prisma community at Prisma Day for a day of inspiring talks and great conversations. See you all tomorrow! 🙌