It’s Time to Move Your System to an ORM

It should have been done long ago. Right at the moment you realized you’d be working with a database. Sure, adopting an ORM now is harder than doing it from day one, but it’s still not too late.

Today I’m going to push my subjective, one-sided, and only correct opinion about why you need an ORM.

There are contraindications for introducing an ORM into your project. Consult your common sense before applying.

That amazing high you get from being useful

Yes, it feels amazing. You started a project the business has needed for years. Not a pet project, not a coursework exercise, an actual business project, funded, real, important. One that finally fixes the broken processes people have been suffering through for ages. You decided to help real humans who struggle with imperfect tools every single day.

We, as engineers, really are wizards. We can fix things. Especially when our eyes shine and our hands itch to make something better. Spending a day writing code so dozens of people save time every day? Every single day? Even when we’ve moved on to completely different things, and they’ll still be saving time. And enjoying it.

Relax, this is not the part where I “bring you back to reality.” We really can do this. That’s why we get paid well. That’s why we enjoy this work. We genuinely like building useful stuff. It feels good to be useful, to be valued. Dopamine, serotonin, whatever, I don’t know the biology behind it, I just threw in a couple of smart words.

It’s a powerful feeling when you take on something and it works. You deliver real value. You’re saving the whole business, the hero in shining armor. People tell you how much better things have become. It warms you. It motivates you.

Well, almost. Because then comes the "If only we could also fix this. And maybe automate that. And we’ve still got this Excel thing over here…"
Once the business gets a taste of blood optimization, it wants more. More. Moar!

That’s it. From this moment you’re officially in the hamster wheel. Solve the hard stuff, and they’ll want the unimaginable. Solve the unimaginable, and they’ll want the impossible. Business has no stop button. Your application has no built-in ceiling. There’s only you, the business, and the system you’re building.

Complexity

With every new feature, the system gets more complex. Every time you add something new, you must consider whether it breaks something old. Keeping all the nuances in your head gets harder and harder.

Meanwhile, the business is getting hooked. They can see your team handling the complex, and now they crave the even more complex. With every cycle, your team’s workload and the system’s complexity grow. The low base effect is long gone, and every new feature now comes with sweat, if not blood.

Complexity is your enemy. Well… ours too, if I’m honest. It’s also the business’s enemy, though it’s nearly impossible to explain this to them. They’ve seen how transformative your system can be, and they expect the magic to continue. You can try explaining, but good luck.

It’s the business’s enemy, because (surprise!) it’s their problem too. Explaining this to them is nearly impossible. They’ve seen with their own eyes how transformative your system can be, and now they expect the magic to continue. You can try but good luck. I won’t offer any advice here, you’re on your own.

You’re hooked on usefulness. The business is hooked too. You both crave the next dose. And then complexity walks in and ruins everything.

I’m not going to tell you how to handle it all. But I will tell you how to reduce your system’s complexity a bit by introducing an ORM, so you can extend your dopamine high, addicts.

Data

The first question in any system: how do we store data? The answer is “database.” Really, what else? Which one? Doesn’t matter, just something that stores data. You’re not going to keep it in Excel, right? So you pick {vendor}SQL.

You chose a relational database. Not because you thought about the word “relational”. You probably didn’t even consider what that meant. But that’s what you picked.

A note for those who chose NoSQL: you’ll regret it. You’ll rewrite it all into an RDBMS. And once you finish rewriting it, you’ll finally understand what NoSQL was actually for. And then migrate part of it to Mongo. Or whatever is fashionable by then.

So, you have a relational database, and you’re using an object-oriented language to work with it. Feel the contradiction forming?

Long story short: object-oriented data structures nest objects inside objects, while relational ones reference things.

I used to think and preach that ORM is exactly this: a bridge between relational tables and object-oriented structures. And yes… well, almost. The problem is unsolvable the general case. But for your specific case? Sure, you can fetch rows and map fields manually. If you couldn’t, what are you even doing here?

Map data once is easy. Keeping it consistent later is the real problem. And even harder is being confident it all stays consistent.

This is where an ORM comes into play.

ORM

An ORM ensures you have a single model for your data, both in the database and in your code. Class fields correspond to table columns. Casting happens automagically. You work with objects as if they weren’t pulled from a database at all, just regular in-memory objects.

ORM is needed so data and application form a single whole. So there’s no difference in code between an object from a dictionary and an object from a repository. Because you, dear friend, need to manage complexity. Less complexity → easier features → more dopamine. Remember?

An ORM is needed so you stop manually juggling fields. Seriously. Stop. Enough. Database fields are database fields, your team works on business logic, which isn’t about individual fields. Sure, it’s not limited to objects either — but let’s at least solve the field problem first.

With an ORM, you can forget about mapping errors. As your system grows, the ORM guarantees that class fields match table columns. Always. You change the database schema and immediately the code that relied on removed fields breaks. Fair enough: just follow the compilation errors and fix the logic. See? Stop shuffling values around by hand. Focus on the logic. An ORM handles this far faster, more reliably, and far more consistently than your biological neural network ever will.

Your code becomes shorter and clearer. Instead of large, fragile, unreliable chunks where SQL in quotes is sent to a command and then you manually pull fields out of a reader and stuff them into objects, you get a short, predictable ORM call. And yes, that hand-written, quote-wrapped SQL will eventually break at runtime gifting you a “pleasant” debugging session long after you’ve forgotten what you were even working on. Do you really want to burn your cognitive resources on that?

Don’t try to work with an ORM without knowing SQL. And don’t involve people who don’t know SQL in ORM work. An ORM is not a replacement for SQL. It works on top of it, adding layers of abstraction, so you need to understand how an ORM query gets translated into SQL. Otherwise, you’ll end up with terrible, slow code and I’ll get blamed for making projects worse with the ORM.

Stop Writing Business Logic Inside the Database

Stop. Really. You simply cannot evolve a complex system inside your database’s stored-procedure language. No matter how skilled you are, you’ll always be working with data, not domain concepts. You’ll always be one or two abstraction levels below those who work with objects.

The fundamental problem with PL/SQL-type languages is that they’re essentially write-only. You won’t notice at first, simple things look innocent. It’s the boiling frog effect. Complexity grows, it gets in the way, and within the database that pain arrives much sooner.

Work in a general-purpose language. As complexity grows, you’ll have more tools to manage it: interfaces, inheritance, encapsulation, libraries from GitHub.

If you write business logic in the database using a general-purpose language, then answer honestly: how are you going to package and integrate it with your main codebase?

Stop writing SQL by hand. It’s faster in the moment, but once your system grows even slightly, you’ll have to update these queries constantly. Every time you add a field, you’ll update your fetch code. Every. Single. Time.

I’m not saying you should completely give up SQL. Sometimes you still need to work with raw data, because doing it through the ORM would be worse. But these are exceptions, not the rule.

Sure, you can automate this. Write a schema synchronizer, generate code from classes, map types. That’s ORM. A simple one, crude and tiny, but an ORM nonetheless. Maybe that’s fine. Maybe that’s the right path.

Either way, it’s time to move your system to an ORM.