Skip to main content

Command Palette

Search for a command to run...

Modern Database Access: Prisma, Drizzle, and ORMs Explained

Updated
β€’16 min readβ€’View as Markdown
Modern Database Access: Prisma, Drizzle, and ORMs Explained

Where does your application data live after a user closes the app?

If a user creates an account, places an order, publishes a blog post, or makes a payment, that information needs to exist somewhere even after the application is closed. That is where databases come in.

As applications grow, however, interacting with databases directly can become repetitive and difficult to maintain. Developers have to deal with queries, relationships, schema changes, validation, migrations, and security concerns.

This is where Object-Relational Mappers (ORMs) and modern database tools such as Prisma and Drizzle become useful.

But before understanding these tools, it is important to understand the problem they are solving.


1. Why Applications Need Databases

Imagine building an e-commerce application.

A user creates an account and adds products to their cart. Later, they close the browser and return the next day.

Should their account and cart disappear?

Obviously not.

Applications need a way to persist data so that information survives application restarts, browser refreshes, and server shutdowns.

A database provides that persistent storage layer.

For example, an e-commerce application might store:

  • Users β€” names, email addresses, passwords, profiles

  • Products β€” names, prices, descriptions, inventory

  • Orders β€” purchased products, quantities, order status

  • Payments β€” transaction information and payment status

A social media application could store users, posts, comments, likes, followers, and messages.

A blogging platform could store authors, articles, categories, tags, and comments.

The database becomes the application's long-term memory.

Structured vs Unstructured Data

Not all data has the same structure.

Consider a user:

Name: Siddhant
Email: siddhant@example.com
Age: 22

This is highly structured. We know exactly what fields exist and what kind of values they contain.

On the other hand, consider a blog post:

"Learning databases changed the way I think about backend development..."

The content itself is less rigidly structured, even though the metadata around it may still be structured.

Databases are designed to store and retrieve this information efficiently while providing mechanisms for consistency, security, querying, and concurrent access.


2. SQL vs NoSQL Databases

One of the first database decisions developers encounter is choosing between SQL and NoSQL.

What is a SQL Database?

SQL databases are generally relational databases.

They organize data into tables consisting of rows and columns.

For example, a users table might look like this:

id name email
1 Siddhant siddhant@example.com
2 Rahul rahul@example.com

Another table might contain orders:

id user_id total
101 1 2499
102 2 1599

The user_id creates a relationship between the two tables.

Popular SQL databases include:

  • PostgreSQL

  • MySQL

  • SQLite

  • Microsoft SQL Server

  • Oracle Database

SQL databases are particularly useful when your application contains strong relationships between entities and requires consistency and structured querying.


What is a NoSQL Database?

NoSQL is a broad category of databases that don't primarily follow the traditional relational table model.

A common type is the document database.

Instead of storing a user across columns in a table, a document database might store something conceptually similar to:

{
  "name": "Siddhant",
  "email": "siddhant@example.com",
  "age": 22
}

Popular NoSQL databases include:

  • MongoDB

  • Redis

  • Cassandra

  • DynamoDB

NoSQL databases can be useful when applications work with flexible or rapidly changing data structures, large-scale distributed workloads, or data models that naturally fit documents or other non-relational structures.

SQL or NoSQL?

There is no universal winner.

A banking system with highly interconnected financial records may benefit heavily from relational modeling and transactions.

A content platform dealing with flexible document structures might benefit from a document-oriented database.

The important question is not:

"Which database is better?"

It is:

"Which data model fits the problem I am solving?"


3. The Problem with Raw Database Queries

Once we have a database, our application needs to communicate with it.

For a SQL database, developers can write SQL queries directly:

SELECT * FROM users WHERE email = 'siddhant@example.com';

To create a user:

INSERT INTO users (name, email)
VALUES ('Siddhant', 'siddhant@example.com');

There is nothing inherently wrong with writing SQL.

In fact, SQL is extremely powerful and remains fundamental to database development.

The problem appears when an application grows.

You may end up writing hundreds or thousands of queries across different parts of the application.

The same database operations can become repeated throughout the codebase:

Controller
   ↓
Service
   ↓
SQL Query
   ↓
Database

Developers also have to think about:

  • Query construction

  • Parameter handling

  • Relationships

  • Data mapping

  • Type safety

  • Error handling

  • Transactions

  • Schema changes

  • Database-specific behavior

Security Concerns

Manually constructing SQL queries can also introduce security vulnerabilities.

For example, concatenating user input directly into a query is dangerous:

const query =
  "SELECT * FROM users WHERE email = '" + email + "'";

If untrusted input is inserted directly into SQL, the application can become vulnerable to SQL injection.

Parameterized queries and other safe database-access patterns help prevent this.

Maintainability

As the application grows, database code can become scattered across controllers, services, utility functions, and business logic.

This makes schema changes harder.

Changing a column or relationship may require developers to manually update many parts of the application.

This is one reason higher-level database abstractions became popular.


4. What is an ORM?

ORM stands for Object-Relational Mapping.

An ORM provides a programming interface that allows developers to interact with relational databases using application-level objects and methods rather than writing every SQL query manually.

The basic idea is:

Application Objects
        ↓
       ORM
        ↓
Relational Database

Suppose we have a User model in our application.

Instead of manually writing:

SELECT * FROM users WHERE id = 1;

an ORM may allow something conceptually similar to:

const user = await db.user.findUnique({
  where: { id: 1 }
});

The ORM translates the application-level operation into the appropriate database interaction.

Why Do ORMs Exist?

ORMs aim to reduce repetitive database code and make database operations feel more natural within the programming language being used.

They can provide:

  • Type safety

  • Query abstractions

  • Relationship handling

  • Schema management

  • Migrations

  • Validation support

  • Better developer tooling

  • Consistent database access patterns

But ORMs are not magic.

They don't eliminate databases, SQL, indexes, transactions, or query optimization.

In fact, understanding SQL and database fundamentals becomes even more valuable when using an ORM.

ORM Tradeoffs

ORMs also introduce another abstraction layer.

Instead of:

Application β†’ Database

you have:

Application β†’ ORM β†’ Database

This can make common operations easier but can sometimes make complex queries harder to reason about.

Potential tradeoffs include:

  • Additional abstraction

  • ORM-specific APIs to learn

  • Generated queries that may need optimization

  • Difficulty expressing some database-specific features

  • Potential performance overhead in certain scenarios

The goal is not to avoid abstraction.

The goal is to choose an abstraction that provides more value than complexity.


5. Understanding Prisma

Prisma is a modern database toolkit commonly used with TypeScript and JavaScript applications.

It provides developers with a strongly typed way to work with databases while offering tools for schema management and migrations.

One of Prisma's central ideas is schema-first development.

A Prisma schema can describe the application's data model:

model User {
  id    Int    @id @default(autoincrement())
  name  String
  email String @unique

  posts Post[]
}

model Post {
  id       Int    @id @default(autoincrement())
  title    String
  content  String?

  authorId Int
  author   User   @relation(fields: [authorId], references: [id])
}

The schema describes entities, fields, relationships, constraints, and other database information.

From this schema, Prisma can generate a type-safe client for interacting with the database.

For example:

const user = await prisma.user.findUnique({
  where: {
    email: "siddhant@example.com"
  }
});

The editor can understand the available models, fields, and types.

That makes database operations easier to discover and reduces certain classes of programming errors.

Prisma Migrations

Prisma also provides migration tooling.

When the application's schema changes, those changes can be represented as migrations.

For example:

Initial schema
      ↓
Add User model
      ↓
Add Post model
      ↓
Add relationship
      ↓
Add index

Instead of manually changing production databases, migration files provide a history of how the schema evolved.

Prisma Developer Experience

One of Prisma's major strengths is developer experience.

The workflow is conceptually:

Define schema
      ↓
Generate client
      ↓
Write type-safe queries
      ↓
Create migrations
      ↓
Deploy

Prisma also has a broader ecosystem around database development, including Prisma Client, Prisma Migrate, Prisma Studio, and related tooling.


6. Understanding Drizzle

Drizzle ORM takes a somewhat different approach.

While Prisma encourages developers to think in terms of a dedicated schema language and generated client, Drizzle emphasizes a SQL-first philosophy.

The goal is to provide type-safe database access while staying close to SQL and relational database concepts.

A simplified Drizzle schema might look like:

import {
  pgTable,
  serial,
  text
} from "drizzle-orm/pg-core";

export const users = pgTable("users", {
  id: serial("id").primaryKey(),
  name: text("name").notNull(),
  email: text("email").notNull().unique()
});

Queries can then remain relatively close to SQL concepts:

const result = await db
  .select()
  .from(users);

This makes Drizzle attractive to developers who already understand SQL and want strong TypeScript integration without moving too far away from the database itself.

Lightweight Architecture

Drizzle is designed to be lightweight and SQL-oriented.

Rather than hiding the database behind a heavily abstracted model layer, it aims to make database operations explicit while providing compile-time type safety.

This can be particularly appealing in modern TypeScript applications where developers want:

SQL concepts
     +
TypeScript type safety
     +
Minimal abstraction

Drizzle is therefore better thought of as a TypeScript-first database toolkit with an SQL-centric approach, rather than simply another layer that hides SQL.


7. Prisma vs Drizzle

Both Prisma and Drizzle solve similar problems, but their philosophies differ.

Area Prisma Drizzle
Philosophy Higher-level developer experience SQL-first
Schema Prisma schema TypeScript schema
Type Safety Strong Strong
SQL Knowledge Helpful but less central More important
Abstraction Higher Lower
Query Style ORM-style API SQL-like API
Migrations Prisma Migrate Drizzle Kit
Learning Curve Generally easier for ORM beginners Easier for SQL-oriented developers
Flexibility High for common application patterns High with SQL-oriented control

Developer Experience

Prisma focuses heavily on making database access intuitive.

The generated client provides autocomplete and clear APIs:

prisma.user.findMany()
prisma.post.create()
prisma.order.findUnique()

For teams that want a polished, opinionated workflow, this can be very productive.

Drizzle provides a more database-oriented experience.

Developers who are comfortable with SQL may appreciate being able to express queries in a way that closely resembles relational database operations.


Learning Curve

For someone new to databases, Prisma can initially feel simpler because the API abstracts many SQL details.

For someone already comfortable with SQL, Drizzle's approach can feel more natural.

However, neither tool removes the need to understand:

  • Tables

  • Primary keys

  • Foreign keys

  • Indexes

  • Joins

  • Transactions

  • Constraints

  • Query performance

Learning the database itself should come before becoming dependent on the abstraction.


Performance Considerations

Performance should not be reduced to:

"Prisma is faster."

or

"Drizzle is faster."

Real-world database performance depends on many factors:

  • Query complexity

  • Database design

  • Indexes

  • Number of queries

  • Network latency

  • Connection management

  • Data volume

  • Caching

  • Database configuration

The difference between two database tools may be insignificant compared with a poorly designed query or missing database index.

For performance-sensitive applications, benchmark the actual workload instead of relying solely on theoretical comparisons.


Migration Workflow

Both ecosystems provide tools for managing schema changes.

The important concept is the same:

Application changes
        ↓
Schema changes
        ↓
Migration
        ↓
Database updated

The exact commands and workflow differ, but both aim to make schema evolution reproducible and manageable.


Ecosystem and Production Use

Prisma has been around longer and has developed a mature ecosystem and strong adoption among JavaScript and TypeScript developers.

Drizzle has gained significant popularity by taking a lightweight, SQL-first approach that fits well with modern TypeScript applications and serverless-oriented environments.

The right choice depends on the project rather than popularity alone.


8. Database Migrations

Applications rarely keep the same database schema forever.

Consider a blogging platform.

Initially, a post may contain:

id
title
content

Later, the product team asks for:

author
published_at
category
slug

Eventually, you might add comments, tags, reactions, and analytics.

The database schema evolves along with the application.

This is where migrations become important.

What is a Migration?

A migration is a versioned change to the database schema.

Conceptually:

Migration 001
Create users

Migration 002
Create posts

Migration 003
Add author relationship

Migration 004
Add published_at

Migration 005
Add index on slug

This creates a history of database changes.

Instead of every developer manually modifying the database, the team can apply the same migration sequence across environments.

Why Migrations Matter

Migrations help with:

  • Version control

  • Team collaboration

  • Reproducible environments

  • Deployment

  • Schema history

  • Rollbacks or recovery strategies

They become especially important once multiple developers and environments are involved.

Common Migration Challenges

Migrations are not completely automatic.

Changing a schema in production can be risky.

For example, deleting a column may destroy data.

Renaming a column may require coordinated application and database changes.

Adding a non-nullable column to a large existing table may require a carefully planned rollout.

As applications grow, database migrations become an important part of deployment architecture rather than just a development convenience.


9. Designing Data Models

Before choosing Prisma, Drizzle, or any ORM, you need to design the data model.

The database should represent the actual relationships in the application.

Consider an e-commerce system.

We may have:

User
Product
Order
OrderItem
Payment

These are our entities.

The next step is understanding how they relate.


One-to-One Relationship

One record is associated with exactly one record of another entity.

For example:

User ─────── Profile
  1            1

A user might have one profile, and that profile belongs to one user.


One-to-Many Relationship

One record is associated with multiple records.

For example:

User
 |
 β”œβ”€β”€ Post
 β”œβ”€β”€ Post
 └── Post

One user can create many posts.

Each post, however, belongs to one author.

This is a very common relationship in blogging and social applications.


Many-to-Many Relationship

Multiple records on both sides can be associated with multiple records.

For example:

Posts  ←→  Tags

A post can have multiple tags.

A tag can belong to multiple posts.

Relational databases commonly represent this using a junction table:

Post
  |
  ↓
PostTag
  ↑
  |
Tag

For example:

PostTag
----------------
post_id
tag_id

This relationship modeling is more important than the ORM syntax used to implement it.

If the underlying data model is poorly designed, switching from Prisma to Drizzle will not fix the architecture.


10. Choosing the Right Tool

So, should you use Prisma or Drizzle?

The answer depends on the project.

For Startup Projects

If the team wants to move quickly and values a polished developer experience, Prisma can be an attractive choice.

Its generated client, schema workflow, and tooling can reduce the amount of repetitive database code developers need to write.

Drizzle can also be a strong option, especially when the team prefers SQL-like control and a lightweight stack.


For Enterprise Applications

Enterprise applications often have complex schemas, large teams, strict migration processes, and long maintenance cycles.

In such environments, the most important factors may be:

  • Team familiarity

  • Database expertise

  • Migration strategy

  • Observability

  • Testing

  • Long-term maintainability

  • Database-specific requirements

The tool should fit the team's engineering practices rather than being selected simply because it is currently popular.


For Teams with Strong SQL Knowledge

If your team already thinks comfortably in SQL, Drizzle's SQL-first approach can be appealing.

It provides type safety without completely hiding the underlying database model.


For Teams Wanting Higher-Level Abstraction

If developers prefer interacting with models through a more abstract and generated API, Prisma can provide a smoother experience.

The tradeoff is that developers need to understand Prisma's abstractions in addition to the database itself.


Final Thoughts

Databases are the foundation of most modern applications.

Before worrying about Prisma or Drizzle, it is important to understand the underlying concepts:

Data
 ↓
Database
 ↓
Schema
 ↓
Relationships
 ↓
Queries
 ↓
Migrations
 ↓
Application

ORMs and database toolkits exist to make this interaction more productive and maintainable.

Prisma emphasizes a high-level, schema-driven developer experience with a generated, type-safe client.

Drizzle takes a more SQL-first approach, keeping developers closer to relational database concepts while providing strong TypeScript support.

Neither is universally better.

The right choice depends on your application's requirements, your team's experience, the complexity of your data model, performance requirements, and how much abstraction you want between your application and database.

And perhaps the most important lesson is this:

Don't choose a database tool before understanding the database problem.

Once you understand tables, relationships, queries, indexes, transactions, and migrations, tools like Prisma and Drizzle become what they are meant to be:

productivity toolsβ€”not magic.

How the Web Works πŸ•ΈοΈπŸ•ΈοΈ

Part 12 of 50

A practical web development series explaining how the web worksβ€”from DNS and browsers to servers, HTTP, APIs, and deploymentβ€”while clearly connecting these fundamentals to real-world website programming using frontend and backend examples.

Up next

Linux File System Hunting: Exploring Linux Beyond Commands πŸ§πŸ”

Most people start learning Linux through commands: ls cd pwd mkdir But after exploring a real Linux environment deeply, I realized something much more fascinating: Linux exposes almost its entire in

More from this blog

Tech with Siddhant

72 posts