How to use Prisma with Hono
Introduction
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.
Prerequisites
1. Set up your project
Create a new Hono project:
npm create hono@latest
- Target directory?
my-app
- Which template do you want to use?
nodejs
- Install dependencies? (recommended)
Yes
- Which package manager do you want to use?
npm
2. Install and configure Prisma
2.1. Install dependencies
To get started with Prisma, you'll need to install a few dependencies:
- Prisma Postgres (recommended)
- Other databases
npm install prisma --save-dev
npm install @prisma/extension-accelerate @prisma/client dotenv
npm install prisma --save-dev
npm install @prisma/client dotenv
Once installed, initialize Prisma in your project:
npx prisma init --db --output ../src/generated/prisma
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:
- A
prisma/
directory with aschema.prisma
file - A
.env
file with aDATABASE_URL
already set
2.2. Define your Prisma Schema
In the prisma/schema.prisma
file, add the following models and change the generator to use the prisma-client
provider:
generator client {
provider = "prisma-client"
engineType = "client"
output = "../src/generated/prisma"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id])
}
This creates two models: User
and Post
, with a one-to-many relationship between them.
2.3. Configure the Prisma Client generator
Now, run the following command to create the database tables and generate the Prisma Client:
npx prisma migrate dev --name init
2.4. Seed the database
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";
const prisma = new PrismaClient();
const userData: Prisma.UserCreateInput[] = [
{
name: "Alice",
email: "alice@prisma.io",
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: "bob@prisma.io",
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 package.json
:
{
"name": "my-app",
"type": "module",
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc",
"start": "node dist/index.js"
},
"prisma": {
"seed": "tsx prisma/seed.ts"
},
"dependencies": {
"@hono/node-server": "^1.19.5",
"@prisma/client": "^6.16.3",
"@prisma/extension-accelerate": "^2.0.2",
"dotenv": "^17.2.3",
"hono": "^4.9.9"
},
"devDependencies": {
"@types/node": "^20.11.17",
"prisma": "^6.16.3",
"tsx": "^4.20.6",
"typescript": "^5.8.3"
}
}
Run the seed script:
npx prisma db seed
And open Prisma Studio to inspect your data:
npx prisma studio
3. Integrate Prisma into Hono
3.1. Create a Prisma middleware
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:
- Prisma Postgres (recommended)
- Other databases
import type { Context, Next } from 'hono';
import { PrismaClient } from '../generated/prisma/client.js';
import { withAccelerate } from '@prisma/extension-accelerate';
function withPrisma(c: Context, next: Next) {
if (!c.get('prisma')) {
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) {
throw new Error('DATABASE_URL is not set');
}
const prisma = new PrismaClient({ datasourceUrl: databaseUrl })
.$extends(withAccelerate());
c.set('prisma', prisma);
}
return next();
}
export default withPrisma;
import type { Context, Next } from 'hono';
import { PrismaClient } from '../generated/prisma/client.js';
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) {
throw new Error('DATABASE_URL is not set');
}
const prisma = new PrismaClient({ datasourceUrl: databaseUrl });
function withPrisma(c: Context, next: Next) {
if (!c.get('prisma')) {
c.set('prisma', prisma);
}
return next();
}
export default withPrisma;
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.
3.2 Environment Variables & Types
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
.
Edit the src/index.ts
to import dotenv
and call the config
method on it.
import { Hono } from 'hono';
import { serve } from '@hono/node-server';
// Read .env and set variables to process.env
import * as dotenv from 'dotenv';
dotenv.config();
Next, Hono needs additional types to 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";
import * as dotenv from "dotenv";
dotenv.config();
type ContextWithPrisma = {
Variables: {
prisma: PrismaClient;
};
};
const app = new Hono<ContextWithPrisma>();
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 contenxt,
so dotenv
can be skipped.
3.3. Create A GET Route
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 });
});
3.4. Display The Data
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 visting 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.
Next Steps
Now that you have a working Hono app connected to a Prisma Postgres database, you can:
- Extend your Prisma schema with more models and relationships
- Add create/update/delete routes and forms
- Explore authentication and validation
- Enable query caching with Prisma Postgres for better performance
More Info
Stay connected with Prisma
Continue your Prisma journey by connecting with our active community. Stay informed, get involved, and collaborate with other developers:
- Follow us on X for announcements, live events and useful tips.
- Join our Discord to ask questions, talk to the community, and get active support through conversations.
- Subscribe on YouTube for tutorials, demos, and streams.
- Engage on GitHub by starring the repository, reporting issues, or contributing to an issue.