apps/docs/content/docs/guides/frameworks/hono.mdx
Prisma ORM offers type-safe database access, and Hono is built for fast, lightweight web apps. Together with Prisma Postgres, you get a fast, lightweight backend, that can be deployed through Node.js, Cloudflare, or many other runtimes.
In this guide, you'll learn to integrate Prisma ORM with a Prisma Postgres database in a Hono backend application. You can find a complete example of this guide on GitHub.
Create a new Hono project:
npm create hono@latest
:::info
my-appnodejsYesnpm
:::To get started with Prisma, you'll need to install a few dependencies:
npm install prisma tsx @types/pg --save-dev
npm install @prisma/client @prisma/adapter-pg dotenv pg
:::info
If you are using a different database provider (MySQL, SQL Server, SQLite), install the corresponding driver adapter package instead of @prisma/adapter-pg. For more information, see Database drivers.
:::
Once installed, initialize Prisma in your project:
npx prisma init --db --output ../src/generated/prisma
:::info You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database like "My Hono Project" ::: This will create:
prisma/ directory with a schema.prisma fileprisma.config.ts with your Prisma configuration.env file with a DATABASE_URL already setIn the prisma/schema.prisma file, add the following models and change the generator to use the prisma-client provider:
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}
datasource db {
provider = "postgresql"
}
model User { // [!code ++]
id Int @id @default(autoincrement()) // [!code ++]
email String @unique // [!code ++]
name String? // [!code ++]
posts Post[] // [!code ++]
} // [!code ++]
// [!code ++]
model Post { // [!code ++]
id Int @id @default(autoincrement()) // [!code ++]
title String // [!code ++]
content String? // [!code ++]
published Boolean @default(false) // [!code ++]
authorId Int // [!code ++]
author User @relation(fields: [authorId], references: [id]) // [!code ++]
} // [!code ++]
This creates two models: User and Post, with a one-to-many relationship between them.
In prisma.config.ts, import dotenv at the top of the file
import { defineConfig, env } from "prisma/config";
import "dotenv/config"; // [!code ++]
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
datasource: {
url: env("DATABASE_URL"),
},
});
Now, run the following command to create the database tables and generate the Prisma Client:
npx prisma migrate dev --name init
npx prisma generate
Let's add some seed data to populate the database with sample users and posts.
Create a new file called seed.ts in the prisma/ directory:
import { PrismaClient, Prisma } from "../src/generated/prisma/client.js";
import { PrismaPg } from "@prisma/adapter-pg";
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL!,
});
const prisma = new PrismaClient({
adapter,
});
const userData: Prisma.UserCreateInput[] = [
{
name: "Alice",
email: "[email protected]",
posts: {
create: [
{
title: "Join the Prisma Discord",
content: "https://pris.ly/discord",
published: true,
},
{
title: "Prisma on YouTube",
content: "https://pris.ly/youtube",
},
],
},
},
{
name: "Bob",
email: "[email protected]",
posts: {
create: [
{
title: "Follow Prisma on Twitter",
content: "https://www.twitter.com/prisma",
published: true,
},
],
},
},
];
export async function main() {
for (const u of userData) {
await prisma.user.create({ data: u });
}
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
Now, tell Prisma how to run this script by updating your prisma.config.ts:
import { defineConfig, env } from "prisma/config";
import "dotenv/config";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
seed: "tsx prisma/seed.ts", // [!code ++]
},
datasource: {
url: env("DATABASE_URL"),
},
});
Run the seed script:
npx prisma db seed
And open Prisma Studio to inspect your data:
npx prisma studio
Inside of /src, create a lib directory and a prisma.ts file inside it. This file will be used to create and export your Prisma Client instance. Set up the Prisma client like this:
import type { Context, Next } from "hono";
import { PrismaClient } from "../generated/prisma/client.js";
import { PrismaPg } from "@prisma/adapter-pg";
import "dotenv/config";
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) {
throw new Error("DATABASE_URL is not set");
}
const adapter = new PrismaPg({
connectionString: databaseUrl,
});
const prisma = new PrismaClient({ adapter });
function withPrisma(c: Context, next: Next) {
if (!c.get("prisma")) {
c.set("prisma", prisma);
}
return next();
}
export default withPrisma;
:::warning We recommend using a connection pooler (like Prisma Accelerate) to manage database connections efficiently.
If you choose not to use one, in long-lived environments (for example, a Node.js server) instantiate a single PrismaClient and reuse it across requests to avoid exhausting database connections. In serverless environments or when using a pooler (for example, Accelerate), creating a client per request is acceptable.
:::
By default, Hono does not load any environment variables from a .env. dotenv handles this and will be read that file and expose them via process.env. Hono can get additional types to know that the withPrisma middleware will set a prisma
key on the Hono context
import { Hono } from "hono";
import { serve } from "@hono/node-server";
import type { PrismaClient } from "./generated/prisma/client.js"; // [!code ++]
type ContextWithPrisma = {
// [!code ++]
Variables: {
// [!code ++]
prisma: PrismaClient; // [!code ++]
}; // [!code ++]
}; // [!code ++]
const app = new Hono<ContextWithPrisma>(); // [!code highlight]
app.get("/", (c) => {
return c.text("Hello Hono!");
});
serve(
{
fetch: app.fetch,
port: 3000,
},
(info) => {
console.log(`Server is running on http://localhost:${info.port}`);
},
);
If using Cloudflare Workers, the environment variables will automatically be set to Hono's context, so dotenv can be skipped.
Fetch data from the database using Hono's app.get function. This will perform any database queries
and return the data as JSON.
Create a new route inside of src/index.ts:
Now, create a GET route that fetches the Users data from your database, making sure to include each user's Posts by adding them to the include field:
import withPrisma from "./lib/prisma.js";
app.get("/users", withPrisma, async (c) => {
const prisma = c.get("prisma");
const users = await prisma.user.findMany({
include: { posts: true },
});
return c.json({ users });
});
Start the Hono app by call the dev script in the package.json
npm run dev
There should be a "Server is running on http://localhost:3000" log printed out. From here, the data
can be viewed by visiting http://localhost:3000/users or by running curl from the command line
curl http://localhost:3000/users | jq
You're done! You've created a Hono app with Prisma that's connected to a Prisma Postgres database. For next steps there are some resources below for you to explore as well as next steps for expanding your project.
Now that you have a working Hono app connected to a Prisma Postgres database, you can: