Apéndice D — D. Glosario de backend de la vida real

Definiciones como las daría un equipo, no un examen

NotaEn una frase

Cada término del libro definido como lo explicaría un compañero en la daily — qué es, para qué existe, y la trampa que esconde. Ordenado por tema, pensado para consulta rápida y repaso en voz alta.

D.1 HTTP y APIs

Endpoint — La pareja verbo + ruta (GET /tasks/5). La API es la colección de endpoints; el contrato es lo que cada uno promete.

Contrato / schema — La forma acordada del request y del response. Existe para que front y back puedan trabajar sin llamarse. Trampa: documentarlo “después” — después nunca llega.

REST — Convención: recursos en la URL, verbos como acciones, JSON como formato, status codes como resultado. No es una ley, es el default que todos entienden.

Idempotencia — Repetir la operación N veces deja el sistema igual que con 1. PUT es idempotente por diseño; POST necesita Idempotency-Key. Trampa: asumir que el cliente no reintenta — siempre reintenta.

Rate limiting — Presupuesto de requests por identidad/ventana. Existe porque el abuso y los bugs de loop se parecen mucho. Devuelve 429 + Retry-After, no un 500 misterioso.

Un bucle repite una acción por cada elemento o hasta cumplir una condición: for task in tasks hace algo con cada tarea. map y filter son bucles disfrazados de funciones — transforman/filtran colecciones sin for explícito.

CORS — Política del navegador: “¿desde qué orígenes puede JS leer esta respuesta?” No es seguridad contra servidores — curl ni lo ve. Trampa: * con credenciales, que los navegadores rechazan (bien).

OpenAPI — El contrato escrito en YAML/JSON que humanos y máquinas leen: documentación viva, clientes generados, tests de contrato. Es la fuente de verdad cuando existe antes que el código.

D.2 Datos

ORM — El traductor objetos↔︎tablas. Ahorra el SQL repetitivo y cobra con N+1 y queries opacas. Regla: ORM para el CRUD, SQL crudo para lo difícil — y siempre poder leer lo que genera.

Un ORM (Object-Relational Mapper) traduce entre objetos del código y filas de la tabla: task.save() en vez de INSERT. Cómodo para el CRUD, peligroso si no sabes qué SQL genera (el N+1 nace ahí).

Una query es la pregunta que le haces a la base de datos en SQL: SELECT * FROM tasks WHERE done = false. La BD traduce la pregunta a un plan de búsqueda — por eso los índices importan.

Migración — Cambio de esquema versionado (up/down) aplicado en orden. Existe porque “la BD de cada quien” no escala a dos personas. Trampa: editar una migración ya aplicada — se crea una nueva, jamás se retoca el historial.

Una base de datos es el programa que guarda datos de forma permanente y los responde rápido. Relacional (Postgres): tablas con relaciones. No relacional: documentos, clave-valor, grafos — cada una para una forma de dato distinta.

Una migración es un cambio versionado del esquema: un archivo que dice “crea esta columna” (up) y “bórrala” (down). Son el historial Git de la estructura de la BD — se aplican en orden y no se editan una vez aplicadas.

Transacción — Grupo de operaciones que se confirman o se revierten juntas (ACID). Existe porque el mundo falla a la mitad. FOR UPDATE = “esta fila es mía hasta el COMMIT”.

Una transacción es un grupo de operaciones que se confirman juntas o no se confirma ninguna: transferir dinero = restar de A y sumar a B. Si falla a la mitad sin transacción, el dinero desapareció.

N+1 — La enfermedad de los loops: 1 query para la lista + N para los hijos. Se cura con JOIN/agregación — una query, no N.

Un JOIN combina tablas por su relación: “cada tarea con el nombre de su proyecto”. Es la superpotencia relacional — en una query traes lo que en NoSQL serían varios viajes.

Pool — Las conexiones a la BD reutilizadas entre requests, porque abrir una por request es caro. Tamaño real: 10–20, no 1000.

Índice — Estructura aparte (B-tree) que convierte búsquedas en saltos. Sigue el patrón de acceso: igualdad primero, orden después. Trampa: indexar todo — cada índice se paga en cada escritura.

Un índice es la tabla de contenido de una tabla: sin él, buscar un usuario es leer las 10 millones de filas (seq scan); con él, es ir directo a la página. Se crea según cómo se consulta, y cada uno cuesta escrituras.

JSONB — Columna JSON indexable dentro del relacional. Decisión cuando el contenido varía por registro; pereza cuando es por no diseñar las tablas.

D.3 Identidad y seguridad

JWT — JSON firmado (no cifrado): el servidor lo emite y verifica sin consultar la BD. Contenido legible para cualquiera — nunca secretos adentro. La firma garantiza integridad, no privacidad.

Refresh token + rotación — El token largo guardado (hasheado) en BD que renueva el access corto. Rotación: cada uso entrega uno nuevo y quema el anterior — reuso detectado = familia entera revocada.

httpOnly cookie — Cookie que JavaScript no puede leer: el XSS que roba tokens no la alcanza. vs localStorage: cómodo pero legible por cualquier script que se cuele.

Un token es una credencial portable: una cadena que dice quién eres y hasta cuándo. El servidor la emite tras el login; el cliente la presenta en cada request en vez de la contraseña.

BOLA / IDOR — “¿Puedo pedir /tasks/99 que es de otra persona?” El #1 de OWASP API. Fix: ownership en la query y 404 (no 403) para lo ajeno — no confirmes que existe.

HMAC / firma de webhook — Hash del body crudo con un secreto compartido: prueba de que el evento viene del proveedor y nadie lo tocó. Se verifica antes de parsear — el JSON re-serializado no firma igual.

Nonce — Número de un solo uso: en webhooks rechaza replays, en auth evita reuso. Pariente del idempotency key.

OWASP API Top 10 — La lista de las 10 formas reales en que mueren las APIs. No es teoría: es la tabla de auditoría por endpoint del cap. 26.

D.4 Operación

Reverse proxy — El portero (nginx/ALB) que recibe el 443, hace TLS y reparte a tu app en :3000. La app nunca ve internet directamente.

Un puerto es una puerta numerada dentro de una computadora: la IP llega al edificio, el puerto al departamento. :3000 = “la app que escucha en el departamento 3000”. Postgres suele usar 5432, HTTP el 80, HTTPS el 443.

12-factor — Las reglas de deploy: config por env vars, procesos sin estado, logs a stdout, mismo artefacto en todos los entornos. La razón por la que tu Dockerfile funciona igual en dev y prod.

Un entorno es una instancia completa donde corre tu app con su propia config y datos: local (tu máquina), staging (réplica de prueba), producción (la real). Cada entorno tiene sus propias llaves y su propia base de datos.

Request ID — El ID único por request que viaja en logs, headers y respuestas de error. Es la diferencia entre “algo falló” y “esta línea de tiempo concreta falló”.

Healthcheck — /health (¿vivo?) y /health/deep (¿BD accesible?). El orquestador decide restart/tráfico según el primero; los humanos diagnostican con el segundo.

Graceful shutdown — Al apagar: dejar de aceptar, terminar lo que corre, cerrar el pool, salir. Lo que convierte un deploy en invisible en vez de una ráfaga de 502.

Un pool es el staff de conexiones a la BD: abrir una conexión por request es caro, así que el pool mantiene ~10–20 abiertas y las presta. El request la usa, la devuelve, y la siguiente la reutiliza.

Migrate-gate — Migrar en CI antes del deploy: el deploy de migración fallida nunca despierta — la imagen verde no sale si la migración no entró.

Runbook — El guion de la 3am: qué mirar, en qué orden, qué comando. La observabilidad convertida en procedimiento — cinco líneas que valen más que veinte gráficas.

D.5 Testing

Pirámide — Muchos unitarios (rápidos), algunos de API (la base real), pocos e2e (frágiles). Invertida = suite lenta que todos ignoran.

Rollback-per-test — Cada test corre en una tx que se revierte al final: tests aislados contra BD real sin sembrar/limpiar. El truco que hace barata la base de la pirámide.

Mock en la frontera — Fingir el adaptador externo (la función que llama a Stripe/SMTP), nunca fetch ni la BD. Mockear la BD es fingir que el SQL funciona — justo lo que el test debía probar.

D.6 Mini reto

Explicar 5 términos en voz alta sin mirar — con la trampa incluida.

La prueba honesta: si al explicar idempotencia mencionaste Idempotency-Key y los reintentos del cliente, lo tienes. Si solo salió “se puede repetir”, vuelve al cap. 22 — la definición sin el para qué es trivia, no conocimiento.

D.7 Vocabulario técnico del capítulo

Un array es una colección ordenada de elementos accedidos por posición: ["a","b","c"][0] es "a" (se cuenta desde 0). Python las llama listas, Go slices — misma idea, distinto acento.

Un objeto es una colección de datos con nombre: {name: "Ana", age: 30} — cada dato es una propiedad (clave → valor). Python los llama dict, Go los arma con struct, TS con objetos/interface.

La autenticación responde “¿quién eres?” — login, contraseña, token. Se confunde con autorización (“¿qué puedes hacer?”), que es la pregunta siguiente. Primero te identificas, luego te dejan o no pasar.

Una cookie es un dato que el servidor pone en tu navegador y el navegador devuelve en cada request. httpOnly = JavaScript no puede leerla (el XSS no la roba); Secure = solo viaja por HTTPS.

Un JWT (JSON Web Token) es un token firmado: el servidor lo genera con su secreto y puede verificarlo sin consultar la BD. Ojo: está firmado, no cifrado — cualquiera puede leer su contenido, pero no modificarlo.

Un hash es una función de un solo sentido: contraseña →$2b\(10\)…`. No se puede revertir — por eso las contraseñas se hashean, no se cifran. bcrypt es lento a propósito: fuerza bruta cara para el atacante.

Un proceso es un programa en ejecución: el sistema operativo le da memoria propia y un lugar en la fila del CPU. Tu API es un proceso; Postgres es otro; el navegador es varios. Que “se caiga el proceso” = el programa murió.

El esquema es el plano de la base de datos: qué tablas hay, qué columnas tiene cada una y de qué tipo. Es contrato: una fila que no cumple el esquema no entra. Se cambia con migraciones, no a mano.

D.8 Lo que deberías saber hacer ahora