This week I explored the Prisma ORM, which simplifies our SQL journey by a LOT. Let’s get right into it!
Topics Covered✅
Last week, I worked with basic schemas and simple database interactions. But once our data starts to grow and multiple entities are involved, raw SQL queries or loosely typed database access quickly become messy and error-prone.
That’s where Prisma comes in.
This week revolved around:
- Understanding what an ORM actually solves
- Defining a database schema using Prisma
- Generating type-safe database clients
- Performing CRUD operations cleanly and safely
1. What is Prisma and why do we need it? 🧠
Prisma is an ORM (Object Relational Mapper). In simple terms, it acts as a bridge between our database and our application code.
Without Prisma, we might write raw SQL like this:
SELECT * FROM users WHERE email = 'test@gmail.com';
With Prisma, the same thing looks like:
const user = await prisma.user.findUnique({
where: { email: "test@gmail.com" }
});
Why this matters
- We don’t manually write SQL for every operation
- Queries become type-safe
- Refactoring database fields doesn’t silently break things
- Autocomplete + compile-time checks save us from runtime bugs
2. Prisma Schema — the single source of truth 📄
First we initialise Prisma in our project (for which you can refer to the docs here).
At the heart of all generated files lies the schema.prisma file. This file defines:
- our database connection
- our models (tables)
- relationships between models
A basic example:
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
createdAt DateTime @default(now())
}
This schema:
- Creates a
Usertable - Automatically enforces uniqueness on email
- Generates types that our editor understands
Once this is written, running:
npx prisma generate
creates a fully typed Prisma Client for us — which we can just import in our DB setup files and use as simply as this -
import { PrismaPg } from '@prisma/adapter-pg'
import { PrismaClient } from "@/app/generated/prisma/client";
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL,
})
const prisma = new PrismaClient({
adapter,
});
3. Migrations — evolving the database safely 🔁
Databases are never static. Fields get added, removed, or changed. Prisma handles this through migrations.
Example:
npx prisma migrate dev --name add-user-model
What this does:
- Creates a migration file
- Applies changes to the database
- Keeps history of schema evolution
This ensures our local DB, staging DB, and production DB all stay in sync. And the generated migration files are simply the SQL versions of the queries that we can write easily using Prisma.
4. CRUD operations with Prisma ✍️
Prisma makes CRUD operations intuitive and readable.
Create
await prisma.user.create({
data: {
email: "nikhil@gmail.com",
name: "Nikhil"
}
});
Read
const users = await prisma.user.findMany();
Update
await prisma.user.update({
where: { id: 1 },
data: { name: "Updated Name" }
});
Delete
await prisma.user.delete({
where: { id: 1 }
});
Each of these operations is:
- Typed
- Validated at compile time
- Predictable in behaviour
And to see what parameters these functions expect we can just refer to the docs.
5. Relations and foreign keys made simple 🔗
Defining relations in Prisma is surprisingly clean.
Example:
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
user User @relation(fields: [userId], references: [id])
userId Int
}
Now Prisma understands:
- One user → many posts
- How to join data internally
- How to fetch nested data safely
Fetching related data:
const user = await prisma.user.findUnique({
where: { id: 1 },
include: { posts: true }
});
New things I learnt this week 🔄
- Prisma acts as an intermediary between our code and database - increasing our ease while also giving type safety, which is an absolute game changer.
- Schema-first design prevents an entire class of bugs
Wrapping up
While Prisma might feel like “just another tool”, it fundamentally changes how confidently we interact with our database. Clean schemas and safe migrations make production systems far more reliable.
If you have any questions or feedback, make sure to comment and let me know! Also, if you have any project ideas for me, please drop em in the comments!
I’ll be back next week with more. Until then, stay consistent!
Top comments (0)