next-forgenext-forge
Mask

Changing the database

How to switch from Neon to something else.

By default, next-forge uses Neon as its database provider. However, you can easily switch to another provider like PlanetScale, Prisma Postgres, Supabase, or any other PostgreSQL/MySQL provider.

Switching from Neon to PlanetScale

Here's a step-by-step guide to switch from Neon to PlanetScale:

  1. Create a new database on PlanetScale and get your connection string. It will look something like this:
mysql://<username>:<password>@<region>.aws.connect.psdb.cloud/<database>
  1. Update your environment variables to use the new PlanetScale connection string:
apps/database/.env
DATABASE_URL="postgresql://<username>:<password>@<region>.aws.neon.tech/<database>"
DATABASE_URL="mysql://<username>:<password>@<region>.aws.connect.psdb.cloud/<database>"
apps/app/.env.local
DATABASE_URL="postgresql://<username>:<password>@<region>.aws.neon.tech/<database>"
DATABASE_URL="mysql://<username>:<password>@<region>.aws.connect.psdb.cloud/<database>"

Etcetera.

  1. Swap out the required dependencies in @repo/database:
npm uninstall @neondatabase/serverless @prisma/adapter-neon ws @types/ws
npm install @planetscale/database @prisma/adapter-planetscale
  1. Update the database connection code:
packages/database/index.ts
import 'server-only';
 
import { Pool, neonConfig } from '@neondatabase/serverless'; 
import { PrismaNeon } from '@prisma/adapter-neon'; 
import ws from 'ws'; 
import { Client, connect } from '@planetscale/database'; 
import { PrismaPlanetScale } from '@prisma/adapter-planetscale'; 
import { PrismaClient } from '@prisma/client';
 
const databaseUrl = process.env.DATABASE_URL;
 
neonConfig.webSocketConstructor = ws; 
 
if (!databaseUrl) {
  throw new Error('Missing DATABASE_URL environment variable.');
}
 
declare global {
  var cachedPrisma: PrismaClient | undefined;
}
 
const pool = new Pool({ connectionString: databaseUrl }); 
const adapter = new PrismaNeon(pool); 
const client = connect({ url: databaseUrl }); 
const adapter = new PrismaPlanetScale(client); 
 
export const database = new PrismaClient({ adapter });
  1. Update your Prisma schema to use the new database provider:
packages/database/prisma/schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
 
generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["driverAdapters"]
}
 
datasource db {
  provider     = "postgresql"
  provider     = "mysql"
  url          = env("DATABASE_URL")
  relationMode = "prisma"
}
 
// This is a stub model.
// Delete it and add your own Prisma models.
model Page {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
}
  1. Add a dev script to your package.json:
packages/database/package.json
{
  "scripts": {
    "dev": "pscale connect [database_name] [branch_name] --port 3309"
  }
}

Switching from Neon to Prisma Postgres

Prisma Postgres is a serverless database with zero cold starts and a generous free tier. You can learn more about its architecture that enables this here.

  1. Create a new Prisma Postgres instance via the Prisma Data Platform and get your connection string. It will look something like this:
prisma+postgres://accelerate.prisma-data.net/?api_key=ey....
  1. Update your environment variables to use the new Prisma Postgres connection string:
apps/database/.env
DATABASE_URL="postgresql://<username>:<password>@<region>.aws.neon.tech/<database>"
DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=ey...."
  1. Swap out the required dependencies in @repo/database:
npm uninstall @neondatabase/serverless @prisma/adapter-neon ws @types/ws
npm install @prisma/extension-accelerate
  1. Update the database connection code:
packages/database/index.ts
import 'server-only';
 
import { Pool, neonConfig } from '@neondatabase/serverless'; 
import { PrismaNeon } from '@prisma/adapter-neon'; 
import ws from 'ws'; 
import { withAccelerate } from '@prisma/extension-accelerate'; 
import { PrismaClient } from '@prisma/client';
 
const databaseUrl = process.env.DATABASE_URL;
 
neonConfig.webSocketConstructor = ws; 
 
if (!databaseUrl) {
  throw new Error('Missing DATABASE_URL environment variable.');
}
 
declare global {
  var cachedPrisma: PrismaClient | undefined;
}
 
const pool = new Pool({ connectionString: databaseUrl }); 
const adapter = new PrismaNeon(pool); 
 
export const database = new PrismaClient().$extends(withAccelerate()); 

Your project is now configured to use your Prisma Postgres instance for migrations and queries.

  1. Explore caching and real-time database events with Prisma Postgres

Note that thanks to the first-class integration of other Prisma products, Prisma Postgres comes with additional features out-of-the-box that you may find useful:

Caching

To cache a query with Prisma Client, you can add the swr and ttl options to any given query, for example:

const pages = await prisma.page.findMany({
  swr: 60, // 60 seconds
  ttl: 60  // 60 seconds
})

Learn more in the Accelerate documentation.

Real-time database events

To stream database change events from your database, you first need to install the Pulse extension:

npm install @prisma/extension-pulse

Next, you need to add your Pulse API key as an environment variable:

apps/database/.env
PULSE_API_KEY="ey...."

Note: You can find your Pulse API key in your Prisma Postgres connection string, it's the value of the api_key argument and starts with ey.... Alternatively, you can find the API key in your Prisma Postgres Dashboard.

packages/database/index.ts
import 'server-only';
import { withPulse } from '@prisma/extension-pulse'; 
import { withAccelerate } from '@prisma/extension-accelerate';
import { PrismaClient } from '@prisma/client';
 
const databaseUrl = process.env.DATABASE_URL;
const pulseApiKey = process.env.PULSE_API_KEY; 
 
if (!databaseUrl) {
  throw new Error('Missing DATABASE_URL environment variable.');
}
 
if (!pulseApiKey) { 
  throw new Error('Missing PULSE_API_KEY environment variable.'); 
} 
 
declare global {
  var cachedPrisma: PrismaClient | undefined;
}
 
export const database = new PrismaClient() 
  .$extends(withAccelerate())              
  .$extends(withPulse({ apiKey: pulseApiKey })) ; 

You can now stream any change events from your database using the following code:

const stream = await prisma.page.stream();
 
console.log(`Waiting for an event on the \`Page\` table ... `);
for await (const event of stream) {
  console.log('Received an event:', event);
}

Learn more in the Pulse documentation.

On this page