Why Prisma is Not an ORM
Prisma is often presented as a “next-generation ORM” that avoids many of the well-known issues of traditional ORMs. While it indeed sidesteps several of these problems, this is not necessarily because it improves upon the ORM paradigm. Rather, it reflects a fundamentally different approach - one that does not fully align with what an ORM is intended to provide.
To understand this distinction, it is useful to first ignore persistence entirely and consider how complex systems are modeled purely in memory.
In-Memory Object Models
A common and well-established approach to modeling complex systems is to represent them as interconnected objects. Each object encapsulates both state and behavior, and objects reference one another, forming a graph-like structure in memory.
In such a model, operations are performed through direct interaction with objects. For example, adding a line item to an invoice is simply a method call:
const invoice = invoices.getOrThrow(id);
const newLineItem = new LineItem(...args);
invoice.addLineItem(newLineItem);
Here, the system operates entirely through references. The invoice object is retrieved, modified via its own behavior, and its internal state changes accordingly. No additional steps are required to “apply” or “persist” the modification.
Iteration over collections follows the same principle:
for (const invoice of invoices) {
const newLineItem = new LineItem(...args);
invoice.addLineItem(newLineItem);
}
This model assumes that objects are long-lived, identity-preserving, and directly mutable through their methods.
The Purpose of an ORM
An ORM (Object-Relational Mapper) exists to bridge this gap. Its purpose is not merely to execute database queries, but to allow developers to continue working with in-memory objects while persistence is handled transparently.
A proper ORM typically provides:
That is why the Repository pattern, in the context of object-relational mapping, was never intended to be a simple holder of SQL queries, but an abstraction that allows working with data as if it were an in-memory collection:
Recommended by LinkedIn
const invoice = invoicesRepository.getOrThrow(id);
const newLineItem = new LineItem(...args);
invoice.addLineItem(newLineItem);
No explicit update operation is required because the system tracks and persists changes implicitly.
Prisma’s Model
Prisma operates differently. Its API encourages explicit interaction with database structures - tables, rows, and columns. Data is retrieved as plain objects, and modifications are applied through explicit operations such as update, create, or upsert.
There is no concept of transparent synchronization between in-memory objects and the database.
Instead, each operation is a discrete interaction with the database. The developer constructs queries, executes them, and receives data that is not inherently tied to a lifecycle or identity beyond that specific call:
const invoice = await prisma.invoice.update({
where: {
id: invoiceId,
},
data: {
lineItems: {
create: {
description: "Development services",
quantity: 2,
unitPrice: 150,
total: 300,
},
},
},
include: {
lineItems: true,
},
});
Conclusion
Because of these characteristics, Prisma does not function as an Object-Relational Mapper in the traditional sense. It does not attempt to preserve the abstraction of an in-memory object graph with transparent persistence.
Instead, it aligns more closely with the Table Data Gateway pattern: a structured and type-safe interface for performing explicit operations on relational data.
This is not a flaw. In many cases, this approach leads to greater clarity and predictability by making database interactions explicit. However, it represents a different abstraction model - one centered around data access rather than object mapping.
For that reason, describing Prisma as an ORM can be misleading. It is more accurately understood as a modern database access layer built on top of relational concepts, rather than a tool that maps objects to relational structures while preserving object-oriented semantics.
Further Reading
nice job!