ORM vs SQL sentiment analysis
Report: how HN has talked about “ORMs vs SQL” over time
Essay context: the 2014 post, “What ORMs have taught me: just learn SQL,” is not quite “never use an ORM.” Its stronger claim is:
ORMs can be useful for describing tables and removing some boilerplate, but they are poor replacements for knowing SQL, especially for queries, reporting, migrations, identity/session behavior, transactions, projections, and performance work.
I used subagents to inspect the HN threads through the HN/Algolia item API, then classified substantive comments into broad sentiment buckets.
Counts are approximate. HN threads contain many nested replies, short rebuttals, jokes, deleted/dead comments, and mixed positions. The most useful reading is the shape of the conversation, not the exact integer counts.
Sentiment buckets
| Bucket | Meaning |
|---|---|
| Pro-SQL / anti-heavy-ORM | Agrees with the essay: learn SQL; ORMs hide important relational/database behavior or create performance/design problems. |
| Pragmatic / hybrid | Use both: ORM for CRUD/mapping/migrations, SQL/query builders/views/procs for complex queries. |
| Pro-ORM / defensive | ORMs solve real problems: type safety, productivity, identity maps, unit-of-work, migrations, boilerplate, safety. |
| Context-dependent | Depends on app type, team skill, DB ownership, language/framework, OLTP vs OLAP, CRUD vs reporting. |
| Other / meta | Tool mentions, jokes, historical/meta discussion, low-signal side discussions. |
Executive summary
HN’s consensus has been surprisingly stable:
Learn SQL. Do not pretend an ORM removes the need to understand the database. But do not confuse “learn SQL” with “never use ORM-like tools.”
The strongest long-running HN position is hybrid:
- ORM or framework model layer for boring CRUD.
- Explicit SQL, query builders, views, stored procedures, jOOQ/sqlc/Ecto/Dapper/JDBI-style tools for complex reads, reports, bulk work, and performance paths.
- Treat heavy object graph/session/lazy-loading ORMs with suspicion.
- Prefer tools that keep the SQL shape visible.
The tone changed over time:
2014 ─────▶ 2016 ─────▶ 2017 ─────▶ 2019 ─────▶ 2020 ─────▶ 2021 ─────▶ 2026
More anti-ORM More pragmatic Tool-rich middle ground Mature hybrid view
“ORMs hurt” “Use both” jOOQ/sqlc/Ecto/Dapper “Typed SQL + escape hatches”
Approximate sentiment counts by repost
Because each thread had a different size, compare proportions more than raw counts.
| Year | Thread size / classified sample | Pro-SQL / anti-heavy-ORM | Pragmatic / hybrid | Pro-ORM / defensive | Context-dependent | Other/meta |
|---|---|---|---|---|---|---|
| 2014 | ~125 substantive comments | ~34 | ~40 | ~24 | ~18 | ~9 |
| 2016 | ~150 substantive comments | ~30 | ~43 | ~42 | ~23 | ~12 |
| 2017 | ~240 substantive comments | ~70 | ~85 | ~50 | ~20 | ~15 |
| 2019 | ~415 substantive comments | ~105 | ~155 | ~95 | ~35 | ~25 |
| 2020 | ~90 substantive comments sampled | ~30 | ~34 | ~16 | ~7 | ~3 |
| 2021 | ~17 substantive comments | ~3 | ~7 | ~5 | ~2 | ~0 |
| 2026 | ~151 substantive comments sampled | ~45 | ~54 | ~34 | ~10 | ~8 |
The repeated pattern: hybrid/pragmatic is usually the largest bucket, followed by either pro-SQL or pro-ORM depending on the year and commenter mix.
2014: strong sympathy with the essay, but already not absolutist
HN item: 8133835
Approx. classified: ~125 substantive comments.
Mood
2014 readers were broadly sympathetic to the essay. Many had fresh Hibernate, ActiveRecord, SQLAlchemy, or enterprise Java scars. The core agreement was:
ORMs make projects feel fast early, then become painful when queries, schema, and performance get real.
But even in 2014, the mature view was not “never use ORMs.” It was:
Use ORMs narrowly. Use SQL when relational work matters.
Notable arguments
- ORMs become tech debt once queries get real. Commenters described projects that started quickly but later required fighting the ORM.
- Object models distort schema design. A recurring point: tables are not object instances; designing schemas around object graphs often hurts later reporting and querying.
- Generated SQL is harder to diagnose. One DBA-style objection: when a generated query is bad, finding and changing the app code responsible can be harder than fixing hand-written SQL.
- Advanced SQL features matter. Window functions, joins, projections, transaction isolation, locking,
SELECT FOR UPDATE, hstore/json, and DB-specific features came up as places ORMs become awkward. - SQL as database API. Several commenters liked the essay’s reframing: the database is a complex data type; queries are its API.
Rebuttals
- Bad raw SQL exists too. Some argued the essay compared good SQL practice against bad ORM practice.
- SQLAlchemy is not Hibernate. SQLAlchemy defenders noted Core, explicit joins, deferred columns, reflection, and composable query expressions.
- Raw SQL does not compose well. Query ASTs, Arel, SQLAlchemy Core, and similar tools were defended as safer than string manipulation.
- ORMs are useful row/object mappers. Even critics liked avoiding hand-written hydration boilerplate.
2014 takeaway
HN mostly accepted the essay’s warning, but the best comments were already converging on:
ORM for simple persistence; SQL/query builders/views/functions for serious relational work.
2016: the defense of modern ORMs gets stronger
HN item: 11981045
Approx. classified: ~150 substantive comments.
Mood
2016 was less “ORMs are bad” and more “this is too black-and-white.”
The pro-ORM side was stronger than in 2014. Commenters argued that modern ORMs had better escape hatches, query inspection, type checking, migrations, and framework integration.
Notable arguments supporting the essay
- ActiveRecord is convenient but weak for nontrivial queries.
- The database may outlive one application. If multiple apps share data, the schema should not be treated as private application state.
- ORMs make easy things easier and hard things harder. This phrase or idea recurred heavily.
- Beginners hidden behind ORMs miss database power. Commenters mentioned Postgres triggers,
LISTEN/NOTIFY, range types, exclusion constraints, logical decoding, and other features many ORM-first developers never discover. - ORM internals become the new thing to learn. If you must understand both SQL and ORM behavior, the abstraction has not removed complexity.
Rebuttals
- Modern ORMs are not all-or-nothing. Hibernate, Django ORM, SQLAlchemy, and others can use raw SQL when needed.
- Django/Rails productivity is real. Admin panels, forms, validation, migrations, permissions, and ecosystem conventions matter.
- Thick clients and long-lived object graphs exist. Identity maps, change tracking, unit-of-work, and object caches are not imaginary features.
- Portability can matter. Some cited migrations from MySQL to Postgres or open-source apps that support multiple DBs.
Distinct 2016 subtheme: stored procedures
The 2016 thread had a richer stored procedure debate.
Pro-stored-procedure arguments:
- DB-side APIs can be source-controlled.
- They avoid round trips.
- They centralize validations for multiple clients.
- SQL IDEs/debuggers/profilers can be good.
Anti-stored-procedure arguments:
- Business logic gets split across app and DB.
- Testing/versioning/deployment can become painful.
- DB logic may scale worse than stateless app servers.
- Real-world stored procedure systems often become hidden mazes.
2016 takeaway
HN was moving toward:
Yes, learn SQL. But “ORMs are bad” is too blunt. Good teams mix ORM, SQL, migrations, query builders, and DB features deliberately.
2017: query builders and jOOQ-style tools become the obvious middle ground
HN item: 15949144
Approx. classified: ~240 substantive comments.
Mood
2017 was one of the clearest “middle path” years.
The anti-heavy-ORM feeling remained strong, but many commenters now had names for the alternative:
- SQLAlchemy Core
- jOOQ
- Dapper
- JDBI
- MyBatis
- query builders
- typed SQL
- micro-ORMs
Notable arguments supporting the essay
- Query builders are the sweet spot. The idea: keep SQL shape visible, but get composition, parameters, and some type help.
- jOOQ over Hibernate. Multiple commenters saw jOOQ as a better fit because it maps SQL clauses almost one-to-one into code.
- ORMs force you to learn two things. Once queries are nontrivial, you need both SQL knowledge and ORM DSL knowledge.
- Object graph hydration is the risky part. The problem is not mapping rows to objects; it is lazy-loaded child collections, sessions, hidden joins, and pretending traversal is free.
- Stored procedures as stable interfaces. Especially for transaction-heavy financial systems, some argued DB-side boundaries are safer and clearer.
- Production performance stories. Entity Framework and Hibernate were repeatedly blamed for generated queries, session cache complexity, flushing surprises, and CPU overhead.
Rebuttals
- Good ORMs automate real work. SQLAlchemy’s creator participated and argued that ORMs help with boilerplate DML, DB/driver quirks, composition, row marshaling, and mapping — but should not hide SQL.
- Avoiding ORMs can lead to a bad custom ORM. Hand-rolled mapping scattered through code can be worse.
- Framework ecosystems matter. Django/Rails ORMs are tied to forms, admin, validation, permissions, migrations, and conventions.
- LINQ/EF defenders emphasized type-safe composability.
2017 takeaway
HN’s sharper distinction became:
The enemy is not row mapping. The enemy is pretending an object graph is a relational query plan.
2019: the largest, most nuanced discussion
HN item: 21031187
Approx. classified: ~415 substantive comments.
Mood
2019 had the richest spread of opinions. It was not anti-ORM in a simple way. It was anti-unexamined heavy ORM.
The dominant view was:
SQL is the domain language. Use it. But typed mapping, query builders, migrations, and framework conventions are useful.
Notable arguments supporting the essay
- SQL is the DSL for relational data. One strong line of argument: avoiding SQL when using an RDBMS is like avoiding the language the database is built to understand.
- Generated SQL can become absurd. Commenters gave Entity Framework stories: giant generated queries replaced by much shorter hand-written SQL.
- N+1 and hidden round trips kill latency. ORMs can make thousands of queries look like ordinary object access.
- Dapper/raw SQL can be dramatically faster. Some reported large speedups after moving hot paths out of EF/Hibernate.
- Dependency complexity does not disappear. Replacing SQL strings with a massive ORM dependency just moves complexity.
- Raw SQL encourages clearer DB/app boundaries. SQL files or HugSQL-like tools make database calls explicit instead of scattered across object methods.
- ORM state management can infect the codebase. Hibernate-style sessions/caches/flushing can become an architectural concern everywhere.
Notable hybrid positions
- ActiveRecord for basic app code; SQL for serious queries.
- CQRS split: ORM on the write side for aggregate persistence; SQL/read models on the read side.
- SQLAlchemy can be both ORM and query builder. Several comments separated “ORM” from “SQL expression builder.”
- Typed SQL/codegen tools gained attention: sqlc, Ecto, jOOQ, Dapper, PetaPoco, OrmLite, Knex, HugSQL.
Rebuttals
- ORMs are for entities, not analytics. Defenders argued that using SQL for reporting does not invalidate ORMs for entity lifecycle.
- Bad use is not a bad tool. Hibernate/Spring Data/EF can work well in ordinary service-style apps.
- Without an ORM, you reimplement one. This was a major pro-ORM argument: serious apps need mapping, parameterization, change tracking, migrations, or conventions somewhere.
- ORMs reduce boilerplate. The “Vietnam of CS” framing was criticized as overdramatic.
- Django/Rails/EF are widely successful for a reason.
Interesting 2019 insight
2019 comments more explicitly separated:
- persistence model
- domain model
- read model
- API model
That is a more mature version of the original essay’s complaint. The issue is not only SQL vs ORM. It is whether one model is being forced to serve every purpose.
2019 takeaway
HN’s 2019 position was close to:
Use SQL for relational thinking. Use ORM-like tools only where they reduce real boilerplate without hiding the query plan or corrupting the model boundaries.
2020: strong “learn SQL” energy, with practical tool recommendations
HN item: 24845300
Approx. classified sample: ~90 substantive comments.
Mood
2020 was lively and opinionated. The thread strongly agreed that SQL skill matters, but again rejected a pure anti-ORM stance.
Notable arguments supporting the essay
- SQL skill has eroded among app developers. Some blamed years of ORM-first Java/web development.
- RDBMS work requires set-oriented thinking. This was one of the strongest technical arguments: ORMs encourage procedural object-by-object thinking, while relational databases are set-oriented.
- Dev databases hide ORM damage. Loading too many rows, filtering client-side, and query loops often look fine locally and fail in production.
- Complex queries are clearer in SQL. Long Spring Data method names and ORM DSL chains were compared unfavorably with straightforward SQL.
- Relations, sessions, eager/lazy loading, and object lifetime are the hard part. Even ORM authors/contributors recognized that no one-size-fits-all solution exists.
- SQL is durable career knowledge. Like HTTP, Unix, or JavaScript, SQL keeps paying off.
Hybrid/pragmatic positions
- “ORM-first, not ORM-only.”
- ORM for CRUD; SQL for reports, monitoring, and bulk/column-oriented work.
- EF plus Dapper/raw SQL fallback.
- Views/materialized views as a clean middle ground.
- Good ORMs should be leaky in the right way: inspect generated SQL, know when to drop down.
- Stored procedures as data-service APIs got another serious airing.
Rebuttals
- The essay attacks a straw ORM. ORMs need not claim to fully abstract the database.
- ORMs save boilerplate and reduce security mistakes.
- Django ORM and EF can be highly capable.
- Type safety and IDE support matter.
- Dynamic query composition is easier with query builders than string concatenation.
2020 takeaway
The most HN-ish 2020 answer:
Do not use an ORM to avoid SQL. Use an ORM, query builder, or typed SQL tool to avoid boring, unsafe, repetitive glue code.
2021: smaller thread, more moderate
HN item: 28812506
Approx. classified: ~17 substantive comments.
Mood
2021 was quieter and more moderate. The dominant response was:
This is a false dichotomy. Use both.
Notable arguments supporting the essay
- SQL is a good DSL designed by database specialists.
- ORM table description plus templated SQL is a strong approach.
- ORM users should know SQL anyway.
Rebuttals
- Hibernate/Spring Data can mix ORM persistence, JPQL, native SQL, and projection mapping.
- Use ORM for 95%, raw SQL for 5%.
- LINQ gives type safety and convenience for common cases.
- Light ORMs give model definitions, migrations, and IDE help without too much magic.
- Raw SQL codebases can be worse: stored procedures, string concatenation, SQL injection risk, repeated mapping code.
Interesting 2021 point
The SQL tooling gap became clearer. Some commenters conceded that raw SQL would be more attractive if IDEs understood embedded SQL, schemas, refactors, and result types better.
2021 takeaway
HN in 2021 sounded less like an argument and more like settled practice:
Know SQL. Use ORM-like tools where they improve safety and ergonomics. Escape freely.
2026: mature hybrid view, with typed SQL and newer ORM defenses
HN item: 48742175
Thread size from API: 264 comments total, 66 top-level.
Classified sample: 151 comments.
Mood
2026 was the most modern version of the debate.
The dominant bucket was still pragmatic/hybrid. But ORM defenses were stronger and more specific:
- EF Core is better than old EF.
- Ecto gets repeated praise.
- Rust
sqlx, Java jOOQ, Go sqlc, and typed query tools are attractive. - LLMs entered the conversation as possible helpers for translating SQL/ORM and spotting N+1 issues.
Notable pro-SQL arguments
- ORMs make easy things easier and hard things harder.
- Generated SQL is a second problem. You need the right query and the right ORM incantation to produce it.
- ORMs are bad for OLAP/bulk workloads.
- ORMs obscure bad access patterns.
- Object graph traversal over relational storage is the core mismatch.
- Schema should model the domain, not ORM convenience.
- Stored procedures and DB-side logic got a more sympathetic reading than older web-dev dogma might suggest.
Hybrid/pragmatic positions
- ORM for simple CRUD, SQL for complicated queries.
- Use only the ORM subset you understand.
- Typed SQL/query builders are the preferred compromise.
- Simple mapping-only tools are fine.
- Ecto was repeatedly praised for being explicit, functional, close to SQL, and avoiding hidden lazy-loading behavior.
- DB functions/table-valued functions as app boundaries appeared as a sophisticated hybrid architecture.
- ORM for input/writes; SQL for output/reads was a concise recurring split.
Rebuttals
- Anti-ORM arguments often attack a strawman. Good ORM users still learn SQL.
- ORMs provide domain-modeling discipline.
- Raw SQL creates serialization/deserialization and schema-change boilerplate.
- Typed data and migrations are real benefits.
- EF Core/LINQ are now much better defended than older EF/Hibernate discussions.
- ORMs reduce accidental SQL injection.
- CRUD-heavy line-of-business apps really exist. Rails/Django-style productivity is not imaginary.
Distinct 2026 themes
1. “ORM” now means too many things
Commenters talked past each other because “ORM” could mean:
- heavy object graph mapper
- ActiveRecord model
- query builder
- typed SQL DSL
- row mapper
- migration tool
- schema definition layer
- unit-of-work/change tracker
A lot of disagreement disappeared when people separated these.
2. Type safety is now the strongest ORM-side argument
The best ORM defenses were no longer “SQL is hard.” They were:
- raw SQL lacks type inference in many editors
- schema drift is painful
- mapping rows into app structs is repetitive
- compile-time checked SQL or typed query DSLs are compelling
3. Lazy loading / N+1 is still the classic failure mode
This has not changed since 2014. The modern answer is not “ignore it”; it is:
- explicit preload,
- query inspection,
- real DB tests,
- performance checks,
- avoiding magical object traversal.
4. The essay aged, but not badly
Some details aged — Postgres JSON support, newer EF Core, Ecto, sqlx, sqlc, jOOQ, better query builders — but the core warning still resonated:
If you use an RDBMS professionally, you need SQL and relational thinking.
2026 takeaway
HN’s 2026 position is probably:
The winning abstraction is not “ORM instead of SQL.” It is “SQL-aware tooling with types, composition, migrations, mapping, and escape hatches.”
How the sentiment changed over time
1. The anti-ORM case became more precise
Early comments often said “ORMs are bad” or “Hibernate is painful.”
Later comments got more specific:
- lazy loading / N+1
- identity map surprises
- session flushing
- object graph traversal
- hidden round trips
- poor projections
- generated SQL observability
- OLTP vs OLAP mismatch
- schema ownership
- domain model vs persistence model confusion
This is a better debate. It avoids the weak version: “ORMs are bad because SQL good.”
2. The pro-ORM case also became more precise
The best ORM defenses shifted from “SQL is tedious” to:
- type safety
- IDE support
- migrations
- parameterization
- composable dynamic queries
- row hydration
- unit-of-work/change tracking
- admin/form/framework integration
- consistent team conventions
- avoiding hand-rolled half-ORMs
That is also a better debate. It avoids the weak version: “developers should not need SQL.”
3. The middle ground got better tooling
Across the years, HN repeatedly recommended:
- SQLAlchemy Core
- jOOQ
- Dapper
- JDBI
- MyBatis
- Ecto
- sqlc
- sqlx
- Knex
- HugSQL
- Arel
- EF Core/LINQ with raw SQL escape hatches
- views/materialized views
- stored procedures/table-valued functions in some architectures
The practical trend is toward SQL-shaped tools, not fully opaque ORMs.
4. Stored procedures became less taboo, but still controversial
The essay wondered whether stored procedures deserved reconsideration.
HN’s answer over time:
- For shared data, financial systems, security boundaries, or heavy data manipulation: maybe yes.
- For ordinary app business logic: be careful.
- The risks are deployment, testing, versioning, hidden side effects, and splitting logic across languages.
- The strongest modern version is not “put everything in stored procs,” but “treat the DB as an API boundary when the data model deserves it.”
5. The stable consensus: SQL is non-optional
Across every repost, the least controversial claim was:
If you are using a relational database, learn SQL.
Even pro-ORM comments usually agreed. The fight is over whether that implies abandoning ORMs.
HN’s answer: usually no.
The best distilled HN position
If you wanted to write the HN consensus as engineering guidance, it would be:
Learn SQL first.
Know joins, indexes, transactions, isolation, query plans, aggregation, constraints, and projections.Do not use an ORM to hide the database.
That fails as soon as performance, reporting, concurrency, or schema evolution matter.Use ORM-like tools for boring glue.
Mapping, migrations, simple CRUD, parameterization, admin/forms, and repetitive model code are real work.Keep complex reads close to SQL.
Use raw SQL, typed SQL, query builders, views, materialized views, stored procedures, or DB functions as appropriate.Avoid magical object graph traversal.
Lazy loading and N+1 are still the classic trap.Prefer transparent, inspectable abstractions.
Good tools make SQL safer and more ergonomic; bad tools make SQL invisible.Separate models when necessary.
Persistence model, domain model, read model, and API model do not have to be the same object.Test against the real database.
Especially if using ORM portability claims, migrations, generated SQL, or DB-specific features.
Final read for an HN audience
HN did not really move from “ORMs good” to “ORMs bad,” or vice versa.
It moved from a somewhat blunt 2014 argument —
“ORMs are painful; just learn SQL.”
—to a more experienced 2026 argument —
“Learn SQL, model relational data relationally, and use the thinnest tool that gives you type safety, mapping, migrations, and composition without hiding the database from you.”
The essay’s title still works as a corrective against ORM-first thinking. But the comment history suggests a better title for the HN consensus:
What ORMs have taught HN: learn SQL, then choose your abstraction carefully.