Skip to main content
Preslav Rachev

It’s not the performance, and neither is it the complexity.

Credits: Caspar Camille Rubin

There are equally many advantages and disadvantages to using an Object-Relational Mapper (ORM). ORMs are great at abstracting database access, which is perfect when you are starting a new project and don’t want to spend time fiddling around with SQL database-specifics early on. Not surprisingly, most tech stacks and well-known frameworks have an ORM, and chances are that you might have used one while working with Ruby on Rails, Django, Laravel, Spring, .NET, etc.

There is the other camp, too - that of the SQL purists. While working with Go, I got to meet many of those. It seems like everyone in the Go community does things a little differently, and database access is a good example. Although there are libraries out there like GORM, and ent, claiming ORM-like capabilities, the consensus around data access is still pretty much “write the SQL yourself.”

As appalling as it may sound to some, there are good arguments for keeping things bare. Performance and transparency are definitely among the top ones. ORMs hide much of the SQL nitty-gritty, which is great, except when it is not. Also, there is often a ton of runtime introspection (i.e., reflection) that is needed so that one can do stuff like:

// Hypothetical Java using a Hibernate-like ORM

var user = userRepo.findUserById(42)

for (var order : user.getRecentOrders(10)) {
	// send an order for shipping and update its DB state
}

// update the entire user chain in a single pass
userRepo.update(user)

Neat, right? Until you have a look at the number of SQL queries and runtime introspections that happen behind the scenes. What’s worse, an ORM would sometimes try to be “smart” and execute everything in a single complex query that becomes the bottleneck of the entire application.

For any operation that an ORM performs, there is likely a simpler SQL query that is 10-100 items faster.

But that’s still not my main issue with ORMs #

I get to work with SQL all the time, and still, I’d be happy to see as little of it in my application code as possible. Stitching strings of SQL spaghetti together gives me as much joy as mixing HTML with regular code. There is a reason people came up with the term “separation of concerns,” and I’m happy to stick to it.

I also don’t work on applications where performance is mission-critical. In most situations, I can easily just pick an ORM, do the job, and call it a day. And I’m sure the same applies to many of your projects, too, whether you like to admit it or not. In most cases, an ORM is just fine.

So, what is this rant about? #

One simple thing that has burned me time and again - the ubiquitous nature of models (or entities). ORMs make it so easy to think of models as plain old regular objects that using them everywhere goes without saying. Want to display the user’s name somewhere? No problem. Load the user model from the DB, and retrieve its name. Did you want the recent orders instead? Of course, you can do the same and lazy-load the orders by simply iterating over the getRecentOrders() result (right in the template). Want to send the entire user model to another service across the wire? Well, you know what to do.

This natural tendency to reuse ORM models everywhere leads to cramming more and more things in them so that we can spare ourselves the effort of a separate type for “just this one tiny thing.” Until you know it, the entire application starts rotating around that same fat model that stretches its tentacles into every single aspect of it … until you realize that other parts of the code now depend on parts of the model, they were not supposed to.

Moral: #

Regardless of whether you use an ORM or not, keep your database models succinct and tied to the persistence layer. When given a chance, create a new model type for the specific use case or layer (API, presentation, logic, etc.). I know these things are tedious, and type conversion is among the most boring stuff in programming, but you will thank me (and yourselves) a few years from now.

Have something to say? Join the discussion below πŸ‘‡

Want to explore instead? Fly with the time capsule πŸ›Έ

You may also find these interesting