Writing raw SQL in a TypeScript project feels like switching languages mid-sentence. Prisma eliminates that context switch — your database schema generates type-safe client code that catches errors at compile time, not in production at 3 AM.
What Prisma Gives You for Free
- Prisma Client — auto-generated, type-safe database queries
- Prisma Migrate — declarative schema migrations
- Prisma Studio — visual database browser and editor
- Full TypeScript inference — every query result is fully typed
- Supports PostgreSQL, MySQL, SQLite, MongoDB, CockroachDB, SQL Server
- Works with any framework — Next.js, Remix, SvelteKit, Express, Fastify
Quick Start
npm install prisma @prisma/client
npx prisma init --datasource-provider postgresql
Schema-First Design
// prisma/schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
createdAt DateTime @default(now())
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User @relation(fields: [authorId], references: [id])
authorId Int
tags Tag[]
}
model Tag {
id Int @id @default(autoincrement())
name String @unique
posts Post[]
}
Run npx prisma generate and you get a fully typed client.
Type-Safe Queries (The Killer Feature)
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// TypeScript KNOWS this returns { id, email, name, posts[] }
const user = await prisma.user.findUnique({
where: { email: 'alex@dev.to' },
include: { posts: true }
});
// This would be a compile error:
// user.nonExistentField ← TypeScript catches it
// Complex queries are also fully typed:
const publishedPosts = await prisma.post.findMany({
where: {
published: true,
author: { email: { contains: 'gmail.com' } }
},
include: { author: true, tags: true },
orderBy: { createdAt: 'desc' },
take: 10
});
Every field, every relation, every filter — fully typed and autocompleted in your IDE.
Migrations That Make Sense
# Create a migration from schema changes
npx prisma migrate dev --name add_user_role
# Deploy migrations in production
npx prisma migrate deploy
# Reset database (development)
npx prisma migrate reset
Prisma compares your schema with the database and generates the SQL migration automatically.
Advanced Patterns
Transactions
const [user, post] = await prisma.$transaction([
prisma.user.create({ data: { email: 'new@user.com', name: 'New' } }),
prisma.post.create({ data: { title: 'First Post', authorId: 1 } })
]);
Raw SQL (when you need it)
const users = await prisma.$queryRaw`
SELECT * FROM "User" WHERE email LIKE ${`%gmail%`}
`;
Middleware
prisma.$use(async (params, next) => {
const before = Date.now();
const result = await next(params);
const after = Date.now();
console.log(`${params.model}.${params.action}: ${after - before}ms`);
return result;
});
Prisma vs Drizzle vs TypeORM
| Feature | Prisma | Drizzle | TypeORM |
|---|---|---|---|
| Type safety | Full (generated) | Full (schema-based) | Partial (decorators) |
| Query syntax | Custom DSL | SQL-like | Active Record/QueryBuilder |
| Migrations | Declarative | SQL or push | Sync/migration |
| Learning curve | Low | Medium | High |
| Raw SQL escape | $queryRaw |
Native SQL | QueryBuilder |
| Performance | Good | Better | Good |
| DX/Tooling | Best (Studio, extensions) | Good | Average |
Who's Using Prisma
- Mercedes-Benz, AT&T, Catchpoint in production
- Default ORM recommendation for Next.js, Remix, tRPC stacks
- 40K+ GitHub stars, 1M+ weekly npm downloads
The Verdict
Prisma makes database work feel like a natural extension of TypeScript. The generated client catches bugs at compile time, migrations are declarative, and Prisma Studio lets you browse your data visually. If you're building a TypeScript backend, Prisma is the safest choice.
Need help building production web scrapers or data pipelines? I build custom solutions for startups and enterprises. Reach out: spinov001@gmail.com
Check out my awesome-web-scraping collection — 400+ tools for extracting web data.
Top comments (0)