Article

SQL vs NoSQL

Published May 08, 2026 · 9 hours, 27 minutes ago

Gastón Gaitan
Gastón Gaitan
Backend Engineer · May 08, 2026
SQL vs NoSQL
Bases de datos · Backend · Arquitectura

SQL vs NoSQL: cuándo usar cada una y por qué existen ambas

Mucha gente piensa que NoSQL vino a reemplazar SQL. No es así. Las bases relacionales y las NoSQL resuelven problemas distintos. Entender esa diferencia es clave para diseñar sistemas escalables, rápidos y mantenibles.

La pregunta clave

¿Por qué usaríamos NoSQL si SQL permite joins, relaciones y queries más potentes? Porque NoSQL sacrifica flexibilidad para ganar escalabilidad horizontal, throughput masivo y latencia predecible.

El cambio de mentalidad

En SQL pensás: "¿cómo relaciono entidades?". En NoSQL pensás: "¿cómo obtengo esta pantalla o endpoint con la menor cantidad de lecturas posibles?".

Regla práctica

Si necesitás flexibilidad y relaciones complejas → SQL. Si necesitás escala gigantesca y access patterns ultra definidos → NoSQL.

Qué es SQL realmente

Las bases SQL están diseñadas alrededor de:

  • Relaciones entre entidades
  • Integridad de datos
  • Joins complejos
  • Queries dinámicas
  • Normalización
  • Consistencia fuerte

Por eso herramientas como PostgreSQL son espectaculares para:

  • ERPs
  • Sistemas bancarios
  • Backoffices
  • Facturación
  • Analytics
  • Dashboards

SQL te deja hacer consultas extremadamente poderosas porque entiende relaciones.

SQL

Joins y modelo relacional

Flexibilidad máxima

En una base relacional, cada tabla representa una entidad distinta y las relaciones se conectan usando claves foráneas.

sql_join.sql

JOIN clásico

La base se encarga automáticamente de relacionar órdenes con usuarios.

SELECT
    o.id,
    u.name,
    u.email
FROM orders o
JOIN users u
    ON o.user_id = u.id
WHERE o.status = 'PAID';
Ventaja brutal de SQL: podés consultar la información de formas nuevas sin haber diseñado previamente cada acceso.
NoSQL

DynamoDB y access patterns

Escala masiva

Bases como DynamoDB no están optimizadas para joins. Están optimizadas para responder extremadamente rápido a patrones de acceso específicos.

La gran desventaja: no hay joins

En SQL, si querés un usuario y sus órdenes, hacés un JOIN y listo. En DynamoDB eso no existe del lado del servidor. Si modelás los datos como en SQL (una tabla users y otra orders), para responder "dame el usuario 123 y todas sus órdenes" tendrías que hacer:

  • Una query a la tabla de usuarios.
  • Otra query a la tabla de órdenes filtrando por user_id.
  • Combinar los resultados en tu backend.

Eso es lento, caro y rompe la principal ventaja de NoSQL (latencia baja y predecible). Por eso el cambio de mentalidad: en vez de pensar:

"¿cómo relaciono usuarios y órdenes?"

pensás:

"¿cómo hago para obtener TODO lo necesario con una sola query?"

La solución: Single Table Design

La técnica clásica de DynamoDB es meter todas las entidades relacionadas en una sola tabla, compartiendo la misma partition key (PK). Así, una sola consulta trae todo lo que necesitás sin joins.

single_table_design.txt

Single Table Design

El perfil del usuario y todas sus órdenes viven bajo la misma partition key (USER#123). La sort key (SK) los diferencia.

PK              SK
USER#123        PROFILE
USER#123        ORDER#1
USER#123        ORDER#2
USER#123        ORDER#3
dynamodb_query.py

Una sola query reemplaza al JOIN

Filtrando por PK = USER#123 traés perfil + órdenes en una sola lectura, sin joins y con latencia constante.

response = table.query(
    KeyConditionExpression=
    "PK = USER#123"
)
DynamoDB sacrifica flexibilidad para ganar velocidad y predictibilidad. El modelo de datos se diseña alrededor de cómo se consulta la información.
Concepto

¿Qué es throughput?

Métrica clave

Throughput es la cantidad de operaciones que un sistema puede procesar por unidad de tiempo. En bases de datos se suele medir en:

  • QPS — queries por segundo
  • RPS — requests por segundo
  • TPS — transacciones por segundo
  • RCU / WCU en DynamoDB — read/write capacity units por segundo

Es importante no confundir throughput con latencia:

Latencia

  • Cuánto tarda UNA operación en responder.
  • Se mide en milisegundos.
  • Ej: "este endpoint responde en 40 ms".
  • Importa para la experiencia del usuario individual.

Throughput

  • Cuántas operaciones podés hacer en paralelo por segundo.
  • Se mide en ops/seg.
  • Ej: "el sistema soporta 50.000 requests por segundo".
  • Importa para soportar muchos usuarios al mismo tiempo.

Una analogía clásica: una autopista. La latencia es cuánto tarda un auto en cruzarla. El throughput es cuántos autos cruzan por minuto. Podés tener latencia baja pero throughput bajo (autopista corta de un solo carril) o latencia más alta pero throughput enorme (autopista larga de 10 carriles).

Por qué importa acá: SQL tiende a tener throughput limitado por la máquina donde corre (vertical). NoSQL distribuye la carga entre muchos nodos, por eso puede sostener throughput masivo (millones de ops/seg) sin perder latencia.
Scaling

Escalamiento vertical vs horizontal

El corazón del tradeoff

Cuando una base de datos empieza a recibir más tráfico del que puede manejar, hay dos formas de hacerla más grande. Esa decisión es lo que separa el mundo SQL del mundo NoSQL.

Vertical (Scale Up)

  • Una sola máquina más grande: más CPU, más RAM, más disco.
  • No cambia la arquitectura, solo el hardware.
  • Fácil de implementar: la app no se entera de nada.
  • Mantiene consistencia fuerte y transacciones ACID sin esfuerzo.
  • Límite físico: el servidor más grande del mundo sigue siendo finito.
  • Caro: el costo crece exponencialmente, no lineal.
  • Si esa máquina se cae, se cae todo (single point of failure).

Horizontal (Scale Out)

  • Muchas máquinas chicas trabajando en paralelo (sharding / clustering).
  • Los datos se reparten entre nodos por una partition key.
  • Escala "infinito": agregás más nodos cuando hace falta.
  • Tolerante a fallos: si un nodo muere, los demás siguen.
  • Costo lineal: hardware commodity barato.
  • Pierde joins fáciles y consistencia fuerte (teorema CAP).
  • Más complejo de operar y de modelar.

¿Por qué SQL prefiere vertical?

Una base relacional garantiza ACID (Atomicity, Consistency, Isolation, Durability) y joins entre tablas. Para mantener eso, el motor necesita ver toda la data en un mismo lugar:

  • Un JOIN entre users y orders requiere leer ambas tablas de forma coordinada. Si están en servidores distintos, el JOIN se vuelve un problema de red distribuido (lento y costoso).
  • Las transacciones (BEGIN ... COMMIT) necesitan bloquear filas. Distribuir locks entre máquinas implica protocolos complejos como two-phase commit, que matan la performance.
  • Las foreign keys exigen verificar integridad referencial en tiempo real. Eso es trivial en una sola máquina y muy caro entre muchas.

Por eso PostgreSQL, MySQL, Oracle y SQL Server escalan principalmente hacia arriba: le metés más RAM, mejores discos NVMe, más núcleos. Sí existen réplicas de lectura y soluciones de sharding (Citus, Vitess), pero son parches sobre un modelo que originalmente fue diseñado para vivir en un solo nodo.

¿Por qué NoSQL nació horizontal?

DynamoDB, Cassandra, MongoDB y compañía nacieron en empresas como Amazon, Facebook y Google donde una sola máquina jamás iba a alcanzar. Entonces el diseño parte de otra premisa:

  • Los datos se reparten entre nodos usando una partition key. Cada query sabe a qué nodo ir.
  • No hay joins server-side, así que no hace falta coordinar nodos para responder una consulta.
  • Se acepta consistencia eventual a cambio de disponibilidad y partición tolerante (lado AP del teorema CAP).
  • Si necesitás más capacidad, agregás nodos. La base redistribuye los datos sola.
Aspecto Vertical (SQL) Horizontal (NoSQL)
Forma de crecer Máquina más potente Más máquinas en paralelo
Tope máximo Limitado por el hardware Prácticamente ilimitado
Costo Exponencial Lineal
Tolerancia a fallos Single point of failure Alta (replica entre nodos)
Consistencia Fuerte (ACID) Eventual (BASE)
Joins Naturales No existen server-side
Idea central: SQL prioriza consistencia y relaciones, y eso encaja mejor con escalar UNA máquina. NoSQL prioriza disponibilidad y throughput, y eso encaja mejor con repartir la carga entre MUCHAS máquinas.
Jerarquía

Por qué SQL no está preparado para datos jerárquicos y NoSQL sí

Hierarchical data storage

Datos jerárquicos = datos con forma de árbol o anidados: un usuario que tiene un perfil, que tiene direcciones, que tienen contactos, que tienen preferencias… O un comentario que tiene respuestas, que tienen sub-respuestas, etc.

El problema en SQL

El modelo relacional es plano por naturaleza: tablas con filas y columnas. Para representar una jerarquía hay que romper el árbol en varias tablas conectadas por foreign keys. Después, para reconstruirlo, hay que hacer múltiples JOINs o consultas recursivas.

sql_jerarquia.sql

Reconstruir un usuario completo en SQL

Hay que unir varias tablas solo para obtener un objeto anidado.

SELECT u.*, p.*, a.*, c.*
FROM users u
LEFT JOIN profiles p   ON p.user_id = u.id
LEFT JOIN addresses a  ON a.user_id = u.id
LEFT JOIN contacts c   ON c.address_id = a.id
WHERE u.id = 123;

Limitaciones reales de SQL frente a jerarquías:

  • Schema rígido: cada nivel del árbol necesita su propia tabla y migraciones para cambiar.
  • Profundidad variable: si un comentario puede tener N niveles de respuestas, tenés que usar recursive CTEs (WITH RECURSIVE), que son lentas y difíciles de mantener.
  • Resultado tabular: el JOIN devuelve una tabla aplanada con datos repetidos. Hay que reconstruir el árbol en código.
  • Escala mal con anidamiento profundo: cada nivel = otro JOIN = más latencia.

Por qué NoSQL lo resuelve naturalmente

Las bases de documentos (MongoDB, DynamoDB, Firestore) guardan el árbol completo como un único documento. La estructura del dato en la base es la misma que en tu app.

nosql_documento.json

El mismo usuario como documento anidado

Un solo findOne() y tenés todo el árbol.

{
  "_id": 123,
  "name": "Pamela",
  "profile": {
    "bio": "Backend dev",
    "avatar": "..."
  },
  "addresses": [
    {
      "city": "BA",
      "contacts": [
        { "type": "phone", "value": "+54..." },
        { "type": "email", "value": "p@x.com" }
      ]
    }
  ]
}

Por qué NoSQL gana acá:

  • Schema flexible: cada documento puede tener una forma distinta. Agregar un campo no requiere migración.
  • Una sola lectura: traer el árbol completo es O(1) consultas, no O(n) joins.
  • Profundidad arbitraria: arrays dentro de objetos dentro de arrays. Sin tablas extra.
  • Localidad de datos: al estar todo junto en disco, una sola lectura física trae la jerarquía completa. Esto encaja perfecto con el sharding horizontal: el árbol entero vive en un nodo.
  • Mismo formato app ↔ DB: JSON entra, JSON sale. Sin ORMs que reconstruyan objetos.
Ojo: esta misma ventaja se vuelve una trampa si los datos jerárquicos también necesitan ser consultados de forma transversal (ej. "todos los contactos email de todos los usuarios"). Ahí SQL vuelve a brillar. La regla sigue siendo: elegí según el access pattern.
Tradeoff

La diferencia REAL entre SQL y NoSQL

No existe magia

SQL

  • Joins complejos
  • Queries dinámicas
  • Relaciones fuertes
  • Integridad referencial
  • Más flexible para consultar
  • Ideal para reporting y analytics
  • Normalización
  • Escala vertical natural

NoSQL

  • Escalabilidad horizontal extrema
  • Latencia muy baja
  • Throughput masivo
  • Alta concurrencia
  • Diseño orientado a access patterns
  • Denormalización
  • Datos jerárquicos nativos
  • Schema flexible
Escala

Por qué TikTok o Netflix usan NoSQL

Millones de requests

El verdadero diferencial de NoSQL no es solamente "una query más rápida". El diferencial es mantener latencias bajas incluso con tráfico monstruoso.

Problema SQL NoSQL
Millones de usuarios concurrentes Más difícil de escalar Escalabilidad horizontal natural
Joins complejos Excelente Malo
Latencia predecible Depende de la query Muy buena
Queries arbitrarias Excelente Muy limitado
Feeds y timelines Posible Excelente
Datos jerárquicos / anidados Requiere muchos JOINs Nativo (documentos)
La clave: DynamoDB funciona increíble cuando ya sabés exactamente cómo se va a consumir la data.
Diseño

La parte difícil de NoSQL

Modelado complejo

Mucha gente cree que NoSQL es "más simple". En realidad, diseñar bien DynamoDB puede ser muchísimo más difícil que diseñar SQL.

Porque necesitás pensar:

  • Cómo se va a leer la información
  • Qué endpoints existen
  • Qué pantallas consume el frontend
  • Qué datos deben duplicarse
  • Cómo evitar múltiples queries

Cuando no podés meter todo en una sola query

A veces el access pattern no encaja en un Single Table Design (por ejemplo: necesitás un listado de órdenes de distintos usuarios). Como NoSQL no tiene joins server-side, la solución es traer las órdenes primero y después resolver la "unión" desde el backend con un BatchGetItem: pedís de una vez todos los usuarios involucrados y los mergeás en memoria.

join_in_memory.py

Join en memoria con batch

1) Traemos las órdenes. 2) Juntamos los user_id. 3) Pedimos todos los usuarios en un solo batch. El "join" lo hace el backend, no la base.

orders = get_orders()

user_ids = [
    o["user_id"]
    for o in orders
]

users = batch_get_users(user_ids)
Error común: usar DynamoDB como si fuera PostgreSQL. Si necesitás joins constantemente, probablemente el modelo está mal diseñado o SQL era una mejor opción.

Entonces… cuál deberías aprender primero

Si estás aprendiendo backend, SQL debería ser tu prioridad.

Porque:

  • Te enseña modelado de datos
  • Te obliga a entender relaciones
  • Es el estándar de la industria
  • Se usa en casi todos los sistemas empresariales

Después, cuando entiendas escalabilidad y arquitectura distribuida, NoSQL empieza a tener muchísimo más sentido.

Cierre rápido

  • SQL Excelente para relaciones, joins y queries complejas. Escala vertical.
  • NoSQL Excelente para throughput masivo y latencia predecible. Escala horizontal.
  • DynamoDB No tiene joins server-side. El diseño gira alrededor de access patterns.
  • Tradeoff Más flexibilidad vs más escalabilidad.
  • Realidad Las empresas grandes usan ambas al mismo tiempo.

Conclusión

SQL y NoSQL no compiten directamente. Son herramientas distintas para problemas distintos.

SQL te da relaciones, consistencia y flexibilidad, y crece haciendo más grande UNA máquina. NoSQL te da escalabilidad horizontal, throughput enorme, datos jerárquicos nativos y latencias muy bajas incluso bajo tráfico gigante, repartiendo el trabajo entre MUCHAS máquinas.

El verdadero seniority no está en elegir "la mejor base de datos". Está en entender qué tradeoffs estás aceptando cuando diseñás un sistema.