apps/blog/content/blog/prisma-orm-support-for-edge-functions-is-now-in-preview/index.mdx
We’re thrilled to share that support for edge functions is in Preview! You can now access your database with Prisma ORM from Vercel Edge Functions, Vercel Edge Middleware, Cloudflare Workers, and Cloudflare Pages. Try it out!
Edge functions are a form of lightweight serverless compute that's distributed across the globe. They allow you to deploy and run your apps as closely as possible to your end users.
Thanks to the geographically distributed nature of edge functions, the distance between the user and the data center is reduced. This decreases request latency and improves response times, making edge functions a great approach to increase performance and notably improve the user experience of an app.
Vercel Edge Functions and Cloudflare Workers don't use the standard Node.js runtime. Instead, they are running code in V8 isolates. As a consequence, these edge functions only have access to a small subset of the standard Node.js APIs and also have constrained computing resources (CPU and memory).
In particular, the constraint of not being able to freely open TCP connections makes it difficult to talk to a traditional database from an edge function. While Cloudflare has introduced a connect() API that enables limited TCP connections, this still only enables database access using specific database drivers that are compatible with that API.
Note: In the Node.js ecosystem, the most popular traditional database driver compatible with Cloudflare Workers is
node-postgresfor PostgreSQL. However, there is also work being done to make MySQL compatible with Cloudflare Workers in thenode-mysql2driver.
Modern database providers, such as Neon or PlanetScale, have worked around this limitation by releasing serverless drivers that talk to the database via HTTP.
While it was possible to use Prisma ORM in an edge function in earlier versions, this always required usage of Prisma Accelerate as a proxy between the edge function and the database.
It was not possible to "just" deploy an app with Prisma ORM to the edge due to the technical constraints mentioned above:
connect()). The problem here was that Prisma ORM only used to have built-in drivers in its query engine and thus couldn't use the compatible Node.js drivers.We are excited that the v5.11.0 release lifts these restrictions and enables running Prisma ORM in edge functions in Preview 🎉
Thanks to the driver adapters Preview feature that was recently introduced, developers can now use Prisma ORM with their favorite database drivers from the Node.js ecosystem!
Additionally, we have been able to drastically reduce the size of Prisma ORM's query engine so that it now fits into the limited runtime environment of an edge function.
🔬 If you're interested in seeing an example in action, we put together a little GitHub repository demonstrating how to access your database using Prisma ORM with Vercel Edge Functions.
Follow along to learn how to get up and running with Prisma ORM in a Cloudflare Worker using a PlanetScale database (or check our docs to use a different combination of edge deployment and database provider).
Before running through the following steps, make sure you have:
Initialize your project using the create-cloudflare-cli and follow the steps in the CLI wizard and select the default options for the prompts:
npm create cloudflare@latest prisma-cloudflare-worker-example -- --type hello-world
Navigate into the new directory and install the Prisma CLI:
cd prisma-cloudflare-worker-example
npm install --save-dev prisma
Next, initialize Prisma in your project with the following command:
npx prisma init --datasource-provider mysql
The above command:
prisma/schema.prisma.env file to store environment variablesThe .env file contains a placeholder DATABASE_URL environment variable.
Update the value with the actual connection string that connects to your PlanetScale database. It may look similar to this:
# .env
DATABASE_URL="mysql://USERNAME:[email protected]/DATABASE?sslaccept=strict"
Note: The connection string above uses placeholders for the username, password and name of your database. Be sure to replace these with the values for your own database.
Update your Prisma schema to look as follows:
generator client {
provider = "prisma-client-js"
previewFeatures = ["driverAdapters"]
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = prisma // required for PlanetScale
}
model Log {
id Int @id @default(autoincrement())
level Level
message String
meta Json
}
enum Level {
Info
Warn
Error
}
The above Prisma schema:
driverAdapters Preview feature flagLog model and Level enumTo map your data model to the database, you need to use the prisma db push CLI command:
npx prisma db push
This created a new Log table in your database that you can now view in the PlanetScale dashboard.
In your wrangler.toml file, add a [vars] key and your database connection string (like before, replace the placeholders for USERNAME, PASSWORD and DATABASE with the values of your own PlanetScale instance):
# wrangler.toml
name = "prisma-cloudflare-accelerate"
main = "src/main.ts"
compatibility_date = "2022-11-07"
[vars]
DATABASE_URL = "mysql://USERNAME:[email protected]/DATABASE?sslaccept=strict"
Note: Since this is a demo app, we're adding the plain connection string into
wrangler.toml. However, as this file is typically committed into version control, you should never do this in production because that would publicly expose your database connection. Instead, use Cloudflare's configuration for secrets.
Next, install the PlanetScale serverless database driver and its driver adapter:
npm install @prisma/adapter-planetscale @planetscale/database
Update the example Cloudflare Worker snippet in the src/index.ts file with the following code:
import { PrismaClient } from '@prisma/client'
import { Client } from '@planetscale/database'
import { PrismaPlanetScale } from '@prisma/adapter-planetscale'
export interface Env {
DATABASE_URL: string
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const config = {
url: env.DATABASE_URL,
// see https://github.com/cloudflare/workerd/issues/698
fetch: (url: any, init: any) => {
delete init['cache']
return fetch(url, init)
},
}
const client = new Client(config)
const adapter = new PrismaPlanetScale(client)
const prisma = new PrismaClient({ adapter })
await prisma.log.create({
data: {
level: 'Info',
message: `${request.method} ${request.url}`,
meta: {
headers: JSON.stringify(request.headers),
},
},
})
const logs = await prisma.log.findMany({
take: 20,
orderBy: {
id: 'desc',
},
})
console.log(JSON.stringify(logs))
return new Response(JSON.stringify(logs))
},
}
Start up the application:
npm run dev
From the terminal output, you can now open the URL pointing to localhost or hit the b key to open your browser and invoke the Worker function.
If everything went well, you'll see output looking similar to this:
[{ "id": 1, "level": "Info", "message": "GET http://localhost:63098/", "meta": { "headers": "{}" } }]
You can now deploy the application by running the following command:
npm run deploy
This command will deploy your edge function to Cloudflare and output the URL where it can be accessed.
We would love to know what you think! Try out the new support for edge deployments using Vercel or Cloudflare and share your feedback with us via X or Discord 🚀
If you run into any issues, you can create a bug report here.