When I started programming a few years back, ORM was like the life blood of software projects. The environment emphasised the tight coupling between the code base and the ORM layer. It can be said that I was trained not to think of projects without an ORM. But as I gained experience and deeper knowledge of […]
When I started programming a few years back, ORM was like the life blood of software projects. The environment emphasised the tight coupling between the code base and the ORM layer. It can be said that I was trained not to think of projects without an ORM.
But as I gained experience and deeper knowledge of specific projects, I realised that most of the improvements are ultimately coming to the point where the flow was entering into ORM framework. That was when I asked myself: what if this project had no ORM?
I started thinking about the problems ORM had introduced:
These may sound like small problems but they significantly hurt productivity. Apart from these, I realised that the ORM ecosystem is detached from mainstream web development with its own brand of issues and limitations. ORMs generally bring unnecessary complexity, providing “leaky abstraction” over database interactions. They sometimes have a steep learning curve and developers tend to treat them as a blackboxes.
I have seen developers take various approaches to tackle the ORM issue. Some completely remove ORM frameworks which is often a Herculean task depending on the complexity of the project. Some accept ORM and adapt code in their project; they’re ready to compromise on the performance and do not care about the added complexity. Many of them choose the golden path where they continue to use the ORM but new or complex queries are excluded. Some of them actually create their own mapping layer specific to the project and according to the need.
So far, I have worked with Hibernate (Java), and Mongoose (ORM framework in Node for MongoDB). When I came to a Node project which was already using Mongoose as an ORM, I had the monumental task of refactoring almost the entire project. At first I thought about removing the ORM framework altogether. But my fellow colleagues would not be satisfied without numbers backing me up. So I benchmarked the query time with and without Mongoose. Here are the results.
They took me by surprise. I had expected a performance gain when not using Mongoose but not to this extent. With this data in hand the choice was clear: ORM was out. A few months later, a colleague asked me whether they should use Sequelize or Pg to access a Postgres database. Realising that Sequelize was an ORM, I gave my vote to Pg, but asked him to benchmark the two. I wanted to verify whether the ORM hate was justified and once the numbers came back, it turns out that it was, indeed, completely justified.
Guess which library he went ahead with.
A thing to remember here is when we gave up ORMs, be it Mongoose or Sequelize, we were aware of what it was that we’re giving up. Specifically schema checking, pre-built methods, abstractions etc. were the perks of using an ORM framework. A major concern was the lack of schema checking (when not using ORMs), something that could lead to bad data entering the DB. To get around this we used Joi, which made our task easier while keeping performance intact. For other parts we needed to write a few lines of extra code but it was worth it. Better that than lose tens of milliseconds (sometimes even seconds) on every query.
I am not trying to bash ORMs and they are really good for beginners and small scale projects. But when your project scales to a large number of queries and documents, ORMs can become a bottleneck. Think of it as the Vietnam of Computer Science – you need to decide when to pull out and run, or else major damage is unavoidable.
Why ORM shouldn’t be your best bet was originally published in Coding Big — The Crowdfire Engineering Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.