• Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
project logo

nmsilva

my-portfolio

Starter template for a markdown blog
Public
Like
my-portfolio
Home
Code
5
docs
4
posts
6
Layout.tsx
README.md
H
index.tsx
Environment variables
Branches
1
Pull requests
Remixes
History
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
posts
/
orm-vs-raw-sql.md
Code
/
posts
/
orm-vs-raw-sql.md
Search
…
Viewing readonly version of main branch: v28
View latest version
orm-vs-raw-sql.md
slug:
orm-vs-raw-sql
date:
Mar 10, 2026
readTime_en:
6 min read
readTime_pt:
6 min leitura
title_en:
Why I stopped using ORM and went back to raw SQL
title_pt:
Por que deixei de usar ORM e voltei ao SQL direto
excerpt_en:
After years of Sequelize and Prisma, I hit a wall with complex queries. Here's what I learned switching back to pg and writing SQL by hand.
excerpt_pt:
Depois de anos com Sequelize e Prisma, cheguei a um limite com queries complexas. O que aprendi ao voltar ao pg e escrever SQL à mão.
tags:
Node.js, PostgreSQL, Backend

The problem with ORMs at scale

I've used Sequelize, TypeORM, and Prisma across different projects. For simple CRUD apps they're great — you get type safety, migrations, and a nice API out of the box. But once your queries grow beyond a few joins, things start to fall apart.

The turning point for me was a reporting query at Dragonboat. It involved multiple CTEs, window functions, and conditional aggregations. The Prisma version was a wall of $queryRaw with TypeScript fighting me every step. The raw SQL version was clean, readable, and 3x faster.

What I switched to

I moved to postgres (the sql package by porsager). It gives you tagged template literals with automatic parameterisation, so SQL injection is still handled correctly:

const users = await sql` SELECT id, name, email FROM users WHERE active = true AND created_at > ${since} ORDER BY created_at DESC LIMIT ${limit} `;

No magic. No hidden N+1 queries. No wondering what SQL your ORM is actually generating.

Migrations

The one thing ORMs genuinely do well is migrations. I replaced that with db-migrate for structured migrations and a simple schema.sql file as source of truth. Not glamorous, but it works.

When I'd still use an ORM

  • Greenfield CRUD-heavy apps where speed of development matters more than performance
  • Teams where not everyone is comfortable with SQL
  • Simple one-table queries where the ORM adds zero friction

For anything else? Write the SQL. You'll thank yourself later.

---pt---

O problema com ORMs em escala

Já usei Sequelize, TypeORM e Prisma em vários projectos. Para apps simples de CRUD são óptimos — tens type safety, migrações e uma API agradável logo de início. Mas quando as queries crescem para além de alguns joins, as coisas começam a correr mal.

O ponto de viragem foi uma query de relatório no Dragonboat. Envolvia múltiplos CTEs, window functions e agregações condicionais. A versão com Prisma era um muro de $queryRaw com TypeScript a lutar contra mim em cada passo. A versão com SQL directo era limpa, legível e 3x mais rápida.

O que adoptei

Mudei para o postgres (o pacote sql do porsager). Oferece template literals com parametrização automática, por isso a injecção de SQL continua a ser prevenida correctamente:

const users = await sql` SELECT id, name, email FROM users WHERE active = true AND created_at > ${since} ORDER BY created_at DESC LIMIT ${limit} `;

Sem magia. Sem queries N+1 escondidas. Sem dúvidas sobre o SQL que o ORM está realmente a gerar.

Migrações

A única coisa que os ORMs fazem genuinamente bem são as migrações. Substituí isso por db-migrate para migrações estruturadas e um simples ficheiro schema.sql como fonte de verdade. Não é glamoroso, mas funciona.

Quando ainda usaria um ORM

  • Apps CRUD-heavy em greenfield onde a velocidade de desenvolvimento importa mais que a performance
  • Equipas onde nem toda a gente se sente à vontade com SQL
  • Queries simples de uma tabela onde o ORM não adiciona fricção

Para tudo o resto? Escreve o SQL. Vais agradecer a ti mesmo mais tarde.

FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
© 2026 Val Town, Inc.