Back to Blog

What is an ORM and when developers should and shouldn't use it

What is an ORM

Object-Relational Mapping (ORM) is a programming technique that facilitates the interaction between a relational database and programming language. It acts as a bridge between the logical, object-oriented representation of data in the code and the physical, relational structure in a database. The primary purpose of an ORM is to eliminate the impedance mismatch that can occur between the object model used in application code and the relational model employed by databases.

Why use an ORM

Developers use ORMs for several reasons. Firstly, it simplifies and accelerates the development process by allowing them to work with objects and classes in the programming language rather than writing SQL queries. This abstraction minimizes the need to deal directly with database-specific syntax and intricacies.

Secondly, an ORM enhances code maintainability by providing some level of an abstraction. Changes to the database schema can be managed more easily, as developers can update the mapping in the ORM layer without extensively modifying application code.

Thirdly, an ORM promotes code reusability and portability. By abstracting the database interactions, developers can write database-agnostic code, making it easier to switch to a different database system without substantial code changes.

Challenges using ORMs

While an Object-Relational Mapping (ORM) layer provides numerous advantages, developers often encounter challenges and trade-offs when deciding to use this approach.

Dev/Build Time Challenges:

  • N+1 Queries: ORMs often lead to the N+1 query problem, where multiple database queries are executed instead of a more optimized query, causing performance issues for data access. Developers need to be mindful of the data access patterns to minimize this problem.
  • Leakiness: As queries become more advanced and complex, beyond basic CRUD operations, the abstraction provided by an ORM can start to leak, forcing developers to direct deal with database-specific query code and behaviors from their code. This can lead to unexpected issues with code maintainability particularly when attempting to change the schema or optimize queries.

Production Performance, Scale, Optimization, and Security:

  • Performance: While ORM systems generate SQL queries, they may not always be ideal and developers may need to fine-tune or handcraft queries for optimal performance in specific situations. In high-performance scenarios, such optimizations become crucial.
  • Scale: As applications scale, ORM-generated queries may not always scale seamlessly. Developers may need to consider database-specific optimizations or even move away from certain ORM features to ensure performance at scale.
  • DB Connection Management: Connection pools manage reusable database connections, enhancing performance and scalability. ORMs may not always integrate seamlessly with connection pools, leading to issues such as inefficient connection management, impacting performance. Additionally, configuring the connection pool settings to align with the ORM's requirements and ensuring proper handling of connections within the ORM layer can be complex tasks.
  • Security: ORM systems abstract away much of the SQL, but developers must remain vigilant about security. Poorly sanitized inputs, improper use of ORM features, or overlooking security configurations can introduce vulnerabilities.

Suitability to SDLC Processes (e.g., CI/CD):

  • Continuous Integration/Continuous Deployment (CI/CD): ORMs can pose challenges in CI/CD pipelines, especially when dealing with database schema changes. Migrations and updates need careful consideration to avoid disruptions and ensure smooth deployment processes.
  • Adaptation to Change: As applications evolve with new features, the ORM mappings may need frequent updates. Ensuring that these changes do not disrupt existing functionality and that migrations are handled seamlessly becomes a crucial aspect of the development process.
  • Modern application architectures: ORM tools may not seamlessly align with modern cloud and serverless architectures. As applications scale, ORM's centralized management of database connections and transactions can become a bottleneck, leading to increased latency and decreased overall throughput. Similarly, in serverless setups, ORM's heavyweight abstraction may struggle with short-lived compute instances. Developers need to carefully evaluate the trade-offs between ORM convenience and cloud-native benefits when architecting applications.

Summary

In conclusion, while an ORM simplifies database interactions and enhances code maintainability, developers should be aware of these challenges and make informed decisions based on the specific needs of their applications. Mitigating these challenges often involves a combination of careful design, optimization, and a deep understanding of both the ORM framework and the underlying database system.