The ORM Is Over: AI-Written SQL Is the New Data Access Layer
ORMs add hidden complexity and unpredictable performance as apps grow. With AI, you can generate clear raw SQL fast and run it safely.
Join the DZone community and get the full member experience.
Join For FreeObject-relational mappers (ORMs) were widely adopted because they abstracted away the need to deal with databases as separate, different things. You could just define your models, use relationships, and the ORM would generate SQL under the hood.
This is a good solution for simple CRUD applications and for quickly getting started, but as your application grows and becomes more complex, the abstraction starts leaking. You may need to use some vendor-specific features that ORM doesn’t support, or when query performance becomes the bottleneck of your application. So, although it’s a trade-off, it might be a good idea to start with SQL instead.
Why ORM Became the Standard
ORMs solved three pain points:
- Speed: We don't have to write SQL for every CRUD endpoint.
- Consistency: Models and relationships gave teams a shared pattern.
- Safety: Parameter binding and abstractions reduced SQL injection risk.
But in production systems, ORMs often become a tax:
- We debug the generated SQL anyway
- We learn both ORM and SQL
- Performance issues show up late
- Complex queries turn into unreadable chains of ORM operators
Core Problem: ORMs Are Leaky Abstractions
Relational databases don’t behave like objects. When the product grows, and data becomes complex, we start needing:
- Partial and tuned indexes
- Query optimizations
- Transaction locking mechanism
- Materialized views
This is where ORMs start falling apart:
- The query looks fine in code, but is slow in production.
- We get N+1 queries without realizing it.
- Seemingly small model changes change SQL output dramatically.
- Eager loading becomes a guessing game.
- ORM becomes a SQL generator that we don't fully control
AI Makes Writing SQL Cheap
SQL lost to ORMs because it was:
- Slower to write the complex queries
- Harder to review
- More prone to errors
Now AI flips the coin, and with the use of AI, developers can:
- Describe the intent, and AI generates the query
- AI can generate multiple SQL Query versions
- Get thorough reviews and explanations
- Performance optimized queries
The New Stack: SQL First, AI-Assisted
A modern ORM replacement is no longer a chaos rather structured SQL platform:
What We Keep
- Migrations
- Schema evolution
- Transactions
- Validation
- Observability
What We Drop
- Heavy object mapping
- Leaky relationship abstractions
- Magic loading behavior
What We Add
- AI-assisted SQL generation
- Query review as part of PRs
- Type-safe wrappers for inputs/outputs
- Performance guardrails (timeouts, limits)
How We Account For This in Our Backend
1. Store SQL Close to the Domain (Not Scattered)
Organize by feature/domain:
- queries/user.sql
- queries/loans.sql
- queries/payments.sql
2. Always Execute Parameterized SQL
Never build SQL by concatenating strings with user input. Examples of safe patterns:
- Postgres: $1, $2, ...
- MySQL: ?
- named params if your driver supports it
3. Use AI as Your Query Pair Programmer
Your best AI prompts are specific:
- "Write Postgres SQL to fetch X with constraints Y, include pagination, avoid N+1."
- "Explain why this query might seq-scan and how to fix it."
- "Provide two variants: CTE and non-CTE."
- "Assume indexes exist on columns A and B; suggest missing indexes."
Then treat the output like human code: review, test, benchmark.
Guardrails That Make This Production-Safe
If you're going SQL-first, these guardrails matter:
Security Guardrails
- parameter binding everywhere
- strict input validation at request boundaries
- least-privilege DB roles (read-only for read paths, separate writer roles)
Performance Guardrails
- statement timeouts
- row limits for endpoints
- pagination by default
- slow query logging + APM traces
- monitoring bechmarks for important transactions
Maintainability Guardrails
- SQL formatting/linting
- integration tests that hit a real DB
- consistent query naming conventions
- code review checklist
Type Safety at Risk Without ORM?
There is no denial about type safety, which ORM provides, but most production bugs aren’t type bugs. They are:
- Wrong joins
- Missing constraints
- Inconsistent transaction boundaries
- Race conditions
- Slow queries and timeouts
We can still get type safety without an ORM by:
- Generating types from schema or queries
- Wrapping SQL calls in typed repository functions
- Validating outputs schema
When ORMs Still Win
ORMs still make sense when:
- Rapid CRUD app development
- Schema is small and stable
- We don't have complex search queries
- We are optimizing for onboarding speed over DB-level control
But once our system scales and starts caring about:
- Performance
- Observability
- Correctness under concurrency
- DB-specific features
Most teams end up writing raw SQL anyway.
Closing Thoughts
In the end, we're not calling ORMs "bad" per se — it's just that, for what backend work looks like today, treating the generated SQL as a first-class artifact has proven more productive. ORMs shine with quick CRUD and simple domains, but as soon as you have a real program that cares about its data in production, you care about the SQL, the indexes, and the query plan. And now that AI has made SQL less painful to generate and iterate on, especially on complex queries, the SQL often turns out to be a more efficient default: We can usually generate it more quickly, look at it with a code diff, run it more safely via parameter binding, and ship it with performance guardrails and observability.
The thinner, more predictable data access layer you get in return is easier to debug, easier to optimize, and more faithful to the actual performance profile of the database.
Opinions expressed by DZone contributors are their own.
Comments