Schema migrations with Prisma and Neon
This tutorial walks you through building a Node.js application with Prisma ORM and Neon, focusing on how to create and apply schema migrations. You'll build a simple book catalog API while learning th...
Pre-built prompt for connecting Node/TypeScript applications to Neon using Prisma ORM.
This tutorial walks you through building a Node.js application with Prisma ORM and Neon, focusing on how to create and apply schema migrations. You'll build a simple book catalog API while learning the migration workflow.
Prerequisites
Section titled “Prerequisites”- A Neon account and project
- Node.js 18+ installed
- Both connection strings from your Neon Console (pooled and direct)
Create the project
Section titled “Create the project”Set up a new Node.js project with Express and Prisma:
mkdir neon-prisma-migrations && cd neon-prisma-migrations
npm init -y
npm pkg set type="module"
npm install express dotenv @prisma/client @prisma/adapter-neon
npm install prisma typescript tsx @types/node --save-dev
npx prisma initConfigure Prisma for Neon
Section titled “Configure Prisma for Neon”Set up environment variables
Section titled “Set up environment variables”Add both connection strings to your .env file. Get these from your Neon Console by clicking Connect:
# Pooled connection for your application (note the -pooler suffix)
DATABASE_URL="postgresql://[user]:[password]@[endpoint]-pooler.[region].aws.neon.tech/[dbname]?sslmode=require"
# Direct (unpooled) connection for Prisma CLI (migrations, introspection)
DATABASE_URL_UNPOOLED="postgresql://[user]:[password]@[endpoint].[region].aws.neon.tech/[dbname]?sslmode=require"Configure prisma.config.ts
Section titled “Configure prisma.config.ts”Update the prisma.config.ts file in your project root:
import 'dotenv/config'
import { defineConfig, env } from 'prisma/config'
export default defineConfig({
schema: 'prisma/schema.prisma',
datasource: {
url: env('DATABASE_URL_UNPOOLED'),
},
})Update the Prisma schema
Section titled “Update the Prisma schema”Replace the contents of prisma/schema.prisma:
generator client {
provider = "prisma-client-js"
output = "../src/generated/prisma"
}
datasource db {
provider = "postgresql"
}
model Author {
id Int @id @default(autoincrement())
name String
bio String?
createdAt DateTime @default(now()) @map("created_at")
books Book[]
@@map("authors")
}
model Book {
id Int @id @default(autoincrement())
title String
authorId Int @map("author_id")
createdAt DateTime @default(now()) @map("created_at")
author Author @relation(fields: [authorId], references: [id])
@@map("books")
}Create and run your first migration
Section titled “Create and run your first migration”Run the following command to create your initial migration:
npx prisma migrate dev --name initThis command:
- Creates a
prisma/migrationsfolder with SQL migration files - Applies the migration to your Neon database
- Generates the Prisma Client
You should see output confirming the migration was applied.
Set up Prisma Client
Section titled “Set up Prisma Client”Create src/db.ts to instantiate Prisma Client with the Neon adapter:
import 'dotenv/config'
import { PrismaClient } from './generated/prisma'
import { PrismaNeon } from '@prisma/adapter-neon'
const adapter = new PrismaNeon({
connectionString: process.env.DATABASE_URL!,
})
export const prisma = new PrismaClient({ adapter })Seed the database
Section titled “Seed the database”Create src/seed.ts to populate the database with sample data:
import { prisma } from './db'
async function seed() {
const authors = [
{
name: 'J.R.R. Tolkien',
bio: 'Creator of Middle-earth and author of The Lord of the Rings.',
books: {
create: [
{ title: 'The Hobbit' },
{ title: 'The Fellowship of the Ring' },
{ title: 'The Two Towers' },
],
},
},
{
name: 'George R.R. Martin',
bio: 'Author of the epic fantasy series A Song of Ice and Fire.',
books: {
create: [
{ title: 'A Game of Thrones' },
{ title: 'A Clash of Kings' },
],
},
},
]
for (const author of authors) {
await prisma.author.create({ data: author })
}
console.log('✅ Database seeded')
}
seed()
.catch(console.error)
.finally(() => prisma.$disconnect())Run the seed script:
npx tsx src/seed.tsBuild the API
Section titled “Build the API”Create src/index.ts with Express endpoints:
import express from 'express'
import { prisma } from './db'
const app = express()
const port = process.env.PORT || 3000
app.get('/authors', async (req, res) => {
const authors = await prisma.author.findMany({
include: { books: true },
})
res.json(authors)
})
app.get('/books', async (req, res) => {
const books = await prisma.book.findMany({
include: { author: true },
})
res.json(books)
})
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`)
})Add a start script to package.json:
npm pkg set scripts.start="tsx src/index.ts"Start the server:
npm startVisit http://localhost:3000/authors to see the data.
Make a schema change
Section titled “Make a schema change”Now let's add a country field to the Author model to demonstrate the migration workflow.
Update the model
Section titled “Update the model”Modify the Author model in prisma/schema.prisma:
model Author {
id Int @id @default(autoincrement())
name String
bio String?
country String?
createdAt DateTime @default(now()) @map("created_at")
books Book[]
@@map("authors")
}Generate and apply the migration
Section titled “Generate and apply the migration”npx prisma migrate dev --name add-author-countryPrisma creates a new migration file and applies it. The Prisma Client is automatically regenerated.
Verify the change
Section titled “Verify the change”Restart your server and check http://localhost:3000/authors. Each author now has a country field (set to null for existing records).
Migration workflow summary
Section titled “Migration workflow summary”The typical workflow for schema changes with Prisma and Neon:
- Modify your schema: Update models in
prisma/schema.prisma - Generate migration: Run
npx prisma migrate dev --name descriptive-name - Review the migration: Check the generated SQL in
prisma/migrations/ - Test locally: Verify your application works with the changes
- Deploy: In production, use
npx prisma migrate deploy
Source code
Section titled “Source code”Find the complete source code for this tutorial on GitHub:
Next steps
Section titled “Next steps”- Connect from Prisma to Neon: Connection setup reference
- Prisma Migrate documentation: Deep dive into Prisma migrations
- Neon branching: Use database branches to test migrations safely
Need help?
Section titled “Need help?”Join our Discord Server to ask questions or see what others are doing with Neon. For paid plan support options, see Support.