Bun is a fast JavaScript runtime that's been making waves in the developer community. It includes a bundler, test runner, and package manager all in one. In this tutorial, we'll explore how to integrate Prisma ORM with Prisma Postgres in Bun to build a simple HTTP server.
The workflow is straightforward: set up Prisma with a Prisma Postgres database, create a simple data model, and build an HTTP server that queries your database. We'll even compile it into a single executable file for deployment.
What We'll Build
In this tutorial, we'll create a simple user management system with:
- Type-safe database queries using Prisma
- A basic HTTP server with Bun
- Seed data for development
- A compiled executable for production deployment
Quick Setup
1. Create your project
mkdir bun-prisma
cd bun-prisma
bun init -y
This creates a basic Bun project with a package.json and index.ts file.
2. Install dependencies
bun add -d prisma
bun add @prisma/client
3. Initialize database
bun prisma init --db
This command does several things:
-
-db: Automatically configures Prisma Postgres for you - Creates a
prisma/directory with yourschema.prismafile - Generates a new Prisma Postgres database
- Creates a
prisma.config.tsfile - Sets up a
.envfile with yourDATABASE_URL
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 like "My Bun Project".
4. Configure direct connection
We're going to use a direct connection string for connecting to Prisma Postgres. To get your direct connection string:
- Navigate to your recently created Prisma Postgres project dashboard
- Click the API Keys tab in the project's sidebar
- Click Create API key
- Provide a name and click Create
- Copy the connection string starting with
postgres://
Update your .env file to replace the DATABASE_URL:
DATABASE_URL="your_direct_connection_string_here"
5. Define your data model
Open prisma/schema.prisma and update it to include a simple User model:
generator client {
provider = "prisma-client"
output = "../generated/prisma"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
}
You can learn more about the Prisma schema in the official documentation.
Setting Up Database Utilities
6. Create a database utility file
Create a db.ts file in your project root to configure PrismaClient:
import { PrismaClient } from "./generated/prisma/client";
export const prisma = new PrismaClient();
This centralizes your Prisma Client instance so you can import it anywhere in your application.
7. Create a seed script
During development, it's helpful to have test data. Create prisma/seed.ts:
import { PrismaClient } from "../generated/prisma/client";
const prisma = new PrismaClient();
async function main() {
await prisma.user.createMany({
data: [
{ email: "alice@example.com", name: "Alice" },
{ email: "bob@example.com", name: "Bob" },
{ email: "charlie@example.com", name: "Charlie" },
{ email: "diana@example.com", name: "Diana" },
{ email: "eve@example.com", name: "Eve" },
{ email: "frank@example.com", name: "Frank" },
{ email: "grace@example.com", name: "Grace" },
{ email: "henry@example.com", name: "Henry" },
{ email: "isabella@example.com", name: "Isabella" },
{ email: "jack@example.com", name: "Jack" },
],
skipDuplicates: true,
});
console.log("Seed data inserted!");
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});
8. Add the seed script to Prisma config
Update prisma.config.ts to include the seed command:
import { defineConfig, env } from 'prisma/config';
export default defineConfig({
schema: 'prisma/schema.prisma',
migrations: {
path: 'prisma/migrations',
seed: `bun run prisma/seed.ts`
},
engine: 'classic',
datasource: {
url: env('DATABASE_URL'),
},
});
Generate Client and Run Migrations
9. Push schema to database
Now we need to migrate the schema to the actual database and generate the Prisma Client:
bunx --bun prisma migrate dev --name init
This command will:
- Create the database tables based on your schema
- Generate the Prisma Client in the
generated/prismadirectory
10. Seed the Database
Run the seed script to populate your database:
bunx --bun prisma db seed
Building Your Bun Server
11. create the HTTP server
Replace the contents of index.ts with the following code:
import { prisma } from './db'
const server = Bun.serve({
port: 3000,
async fetch(req) {
const { pathname } = new URL(req.url)
// Skip favicon route
if (pathname === '/favicon.ico') {
return new Response(null, { status: 204 })
}
// Return all users
const users = await prisma.user.findMany()
// Count all users
const count = await prisma.user.count()
// Format the response with JSON
return new Response(
JSON.stringify({
users: users,
totalUsers: count,
}),
{ headers: { 'Content-Type': 'application/json' } },
)
},
})
console.log(`Listening on http://localhost:${server.port}`)
This creates a simple HTTP server that fetches all users from the database and returns them as JSON along with the total count.
Running your application
Start your Bun server:
bun run index.ts
You should see Listening on http://localhost:3000 in the console. Visit http://localhost:3000 in your browser to see a JSON response with all the users in your database.
Building a Production Executable
One of Bun's coolest features is the ability to compile your TypeScript application into a single executable file. This is incredibly useful for deployment and distribution.
12. Build the Executable
bun build --compile index.ts
This creates an executable file named index (or index.exe on Windows) in your project directory.
13. Run the executable
./index
You should see the same Listening on http://localhost:3000 message, and your application will work exactly the same as before. The executable includes all dependencies and can be deployed to any compatible system without requiring Bun or Node.js to be installed.
Why use Bun executables?
- Deployment: Ship a single file instead of managing dependencies
- Distribution: Share your application without requiring users to install Bun
- Performance: Faster startup times compared to running TypeScript files
- Security: Your source code is compiled and not easily readable
Key advantages of this approach
Fast Runtime: Bun is significantly faster than Node.js for many operations, including server startup and package installation.
Type Safety: Prisma provides full type safety for your database queries, catching errors at compile time rather than runtime.
Simple Deployment: The compiled executable makes deployment straightforward - just copy one file to your server.
All-in-One Tooling: Bun includes everything you need (bundler, test runner, package manager) without additional dependencies.
Top comments (0)