Database Setup
PostgreSQL database configuration with Neon and Prisma Accelerate
Database Setup
Jose Madrid Salsa uses PostgreSQL as its primary database, hosted on Neon with optional Prisma Accelerate connection pooling.
Architecture
App (Vercel) ──> Prisma Accelerate (pooled) ──> Neon PostgreSQL
│
└── prisma:// or prisma+postgres:// URLFor migrations and seeding, a direct (unpooled) connection bypasses Accelerate:
npx prisma migrate ──> Neon PostgreSQL (direct)
│
└── postgresql:// URL via DATABASE_URL_UNPOOLEDPrisma Schema Datasource
The schema is configured in prisma/schema.prisma:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
directUrl = env("DATABASE_URL_UNPOOLED")
}urlis used at runtime. When it starts withprisma://orprisma+postgres://, the Prisma client automatically activates the Accelerate extension.directUrlis used byprisma migrateandprisma db pushto connect directly to the database.
Connection Resolution
The Prisma client in lib/prisma.ts resolves the database URL with a fallback chain:
DATABASE_URL(primary)PRISMA_DATABASE_URL(first fallback)POSTGRES_URL(second fallback, set by Vercel Postgres integration)
const resolveDatabaseUrl = () => {
if (!process.env.DATABASE_URL) {
if (process.env.PRISMA_DATABASE_URL) {
process.env.DATABASE_URL = process.env.PRISMA_DATABASE_URL
} else if (process.env.POSTGRES_URL) {
process.env.DATABASE_URL = process.env.POSTGRES_URL
}
}
return process.env.DATABASE_URL
}Prisma Accelerate
When the resolved URL uses the prisma:// or prisma+postgres:// protocol, the client automatically extends itself with withAccelerate():
const usesAccelerate = databaseUrl.startsWith('prisma://')
|| databaseUrl.startsWith('prisma+postgres://')
if (usesAccelerate) {
const baseClient = new PrismaClient({ log: logLevels })
return baseClient.$extends(withAccelerate())
}Prisma Accelerate provides connection pooling, query caching, and global edge caching. It is recommended for production but not required for local development.
Lazy Initialization
The Prisma client uses a Proxy-based lazy initialization pattern. The client is not created when the module loads -- it is created on the first property access. This avoids connection errors during Vercel build time when DATABASE_URL may not be available:
export const prisma: PrismaClient = new Proxy({} as PrismaClient, {
get(target, prop) {
const client = getPrismaClient()
const value = (client as any)[prop]
return typeof value === 'function' ? value.bind(client) : value
}
})Local Development
Install PostgreSQL
Use Homebrew on macOS or install Docker:
# macOS with Homebrew
brew install postgresql@16
brew services start postgresql@16
# Or use Docker
docker run -d --name jms-postgres \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_DB=josemadridsalsa \
-p 5432:5432 postgres:16Configure Environment
DATABASE_URL="postgresql://postgres:password@localhost:5432/josemadridsalsa"Run Migrations
npx prisma migrate devSeed the Database
npx prisma db seedProduction Setup (Neon)
Create a Neon Project
Sign up at neon.tech and create a new project with PostgreSQL 16.
Get Connection Strings
From the Neon dashboard, copy:
- Pooled connection string for
DATABASE_URL - Direct connection string for
DATABASE_URL_UNPOOLED
Add to Vercel
In the Vercel dashboard, go to Settings > Environment Variables and add both connection strings for Production, Preview, and Development environments.
Deploy Migrations
Migrations run automatically as part of the build process, or you can run them manually:
DATABASE_URL_UNPOOLED="postgresql://..." npx prisma migrate deployBinary Targets
The Prisma client is configured to generate binaries for both local development and the Vercel serverless runtime:
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "rhel-openssl-3.0.x"]
}The rhel-openssl-3.0.x target is required for Vercel's Amazon Linux 2023-based runtime.
How is this guide?
Last updated on