Why would you ever use an ORM?

Published: (December 3, 2025 at 06:50 AM EST)
5 min read
Source: Dev.to

Source: Dev.to

Cover image for Why would you ever use an ORM?

Software development is always a search for balance between multiple aspects: development speed (how fast you ship new features), application performance, memory consumption, UI quality, and the cleanliness of your business logic.

In most cases, development speed is more important than performance or memory consumption. Performance is often “good enough,” memory usage is often “acceptable,” but development speed directly affects business profitability. There is never “too much” development speed—it determines how much money the business will spend on building the product and how long it will stay under the pressure of risk. If you are targeting a competitive market and your rivals can launch earlier, then nothing is more critical.

Of course, an application that barely moves or consumes absurd amounts of memory won’t survive competition. But if you compare speeding up an app by 20 % with saving two or three months of development time, the choice is obvious. Users may not notice the extra 20 % speed, but the budget hole will definitely be noticed.

How an ORM speeds up development

ORM is a tool designed to save development time. But how exactly?

  • Shorter code – It hides the boilerplate required to move values between table columns and class fields. This also ensures type safety: the type of a class field always matches the database column type.
  • IDE support – Autocomplete works everywhere, improving developer experience and correctness, which means faster work.
  • Reduced cognitive load – Shorter, more readable code is quicker to write and quicker to understand, especially in large projects where the limiting factor is human brain capacity.
  • Higher‑level abstraction – ORMs expose objects instead of raw fields. You can take a common base query and modify it for multiple specific cases using polymorphism, or add conditions dynamically depending on user input. Doing the same with raw SQL is significantly harder.
  • Fewer errors – When writing SQL by hand, it’s easy to make a mistake in one of dozens of fields. An ORM won’t make that mistake and will automatically update all queries when you add or rename fields, eliminating an entire class of human‑factor errors and saving huge amounts of debugging time.
  • Simplified refactoring – Cleaning up and reorganizing the schema is dramatically easier with an ORM. Schema refactoring can accelerate long‑term development by an order of magnitude.

Yes, a new abstraction layer adds some entry complexity. If your project has ten tables that rarely change, you probably don’t need an ORM at all. ORMs exist to manage high complexity, and small projects simply don’t have that complexity.

Impact on performance

Earlier, I said that development is a search for compromise. Does using an ORM mean losing performance or increasing memory usage? Not necessarily.

  • An ORM introduces some overhead for building queries and mapping data, but compared to database I/O this overhead is negligible.
  • Shorter code and easier algorithmic optimization often make ORM‑based logic faster than raw SQL in the long term. Raw SQL can be optimized, but it’s harder to see the full picture, and developers are often reluctant to touch something that works for fear of breaking it.
  • Paradox – Raw SQL may run slightly faster when first written, but after many iterations of development the ORM version often ends up significantly faster due to incremental cleanups and safer refactoring.

Some argue that ORMs make it too easy to generate excessive queries, especially when used by junior developers who don’t understand SQL. The truth is simple: to use an ORM properly you must know SQL. You need to understand what SQL is generated by your language‑level expressions. An ORM is not a replacement for SQL; it is an abstraction layer on top of SQL.

Memory consumption

Memory consumption isn’t straightforward either.

// Example: a DataTable row may occupy far more memory than a simple typed field
Int32 value; // occupies 4 bytes (plus possible overhead in managed environments)

I’ve seen developers load entire tables into DataTable objects and then work with them as if they were Excel sheets. In such structures, an Int32 may occupy 8 bytes on the stack plus 24 bytes on the heap (CLR, x64). ORMs store data in typed fields, which reduces memory usage drastically.

Database query results are inherently flat tables. Imagine a table with 100+ columns (e.g., orders) joined one‑to‑many with a table of 5 fields (positions). If you store the result “as is,” every position record duplicates all 100+ fields from the left table. Memory waste can become ten‑fold or even hundred‑fold. A good ORM groups child rows under a single parent instance instead of duplicating all the data.

Schema synchronization

The first task of any ORM is to keep the database schema and application objects in sync. This is the essence of mapping: loading table columns into class fields and writing them back. To do this correctly, the ORM must take the “original” schema definition at compile time. That definition can come from the database (db‑first), from code (code‑first), or from a separate model (model‑first).

  • Code‑first projects the schema from code into the database. It’s convenient when you have multiple environments, but it breaks down when multiple independent services try to reshape the database to suit themselves. Synchronization becomes complex because it requires loading the existing schema, comparing it correctly, and generating intricate DDL.
  • DB‑first and model‑first rely on code generation of entity classes. This is simpler: load the schema from the database (or from the model file) and regenerate the entity files.

In practice, schema synchronization always has project‑specific requirements. You may need to extend generation for custom rules (e.g., import database comments into entity files, handle many‑to‑many links through text columns, or map enums with custom logic). Built‑in ORM generators are often closed and not easily customizable.

A common criticism of ORMs is this rigidity. One solution is to use open‑source generators. For example, the MIT‑licensed OrmFactory can be modified for your project’s needs. It works directly with the database and can export the schema into your project, handling schema design and synchronization while leaving the ORM to do what it does best—mapping.

Back to Blog

Related posts

Read more »

Bf-Trees: Breaking the Page Barrier

Hello, I'm Maneshwar. I'm working on FreeDevTools – an online, open‑source hub that consolidates dev tools, cheat codes, and TLDRs in one place, making it easy...