Apéndice C — C. El mapa universal
Qué vive en el lenguaje, qué en el framework, qué en la industria
La tabla de tres columnas con todos los conceptos del libro clasificados — ahora con evidencia en los tres stacks. Cuando cambies de stack, la columna derecha es tu equipaje completo; las otras dos son solo sintaxis nueva.
C.1 El mapa completo
| Concepto | Del lenguaje | Del framework | De la industria (te lo llevas) | Cap. |
|---|---|---|---|---|
| Async/concurrencia | event loop / asyncio / goroutines | — | I/O-bound se paraleliza, CPU-bound no | 20 |
| Tipos en la frontera | anotaciones | zod / pydantic / decoder | validar antes de tocar | 4 |
| Routing | — | Express / FastAPI / ServeMux | recursos, verbos, contrato | 3 |
| Inyección de deps | — | Depends / closures / params | construir en el borde, pedir adentro | 16 |
| Errores | throw / raise / return err | handler global | dominio → mapper → {error:{code}} |
6, 25 |
| Auth | — | middleware/Depends/wrapper | bcrypt, JWT corto + refresh rotado | 14–18 |
| Autorización | — | Depends/factory | rol en la relación, ownership en la query | 17 |
| BD | — | pg / psycopg / pgx | pool, parametrizar, tx, FOR UPDATE | 10, 13 |
| Migraciones | — | dbmate / alembic / goose | versionadas, up+down, sin editar viejas | 11 |
| Índices/N+1 | — | — | EXPLAIN, igualdad→orden, LIMIT 21 | 12 |
| Integraciones | fetch / httpx / http.Client | — | timeout, retry, degradación, adapter | 19 |
| Jobs | — | setInterval / BackgroundTasks / ticker | “¿espera el usuario?” → si no, job | 21 |
| Webhooks | — | — | firma sobre body crudo, dedupe, 200 rápido | 22 |
| Logs | — | pino / logging / slog | JSON + request_id, nunca secretos | 23 |
| Config | — | dotenv / pydantic-settings / env | 12-factor, fail-fast, sin defaults secretos | 24 |
| Seguridad | — | — | OWASP auditada por endpoint, 404 vs 403 | 26 |
| Testing | — | vitest / pytest / go test | pirámide, rollback-per-test, mock en frontera | 27–29 |
| Deploy | binario vs runtime | — | imagen única, env vars, healthcheck, migrate-gate | 30–35 |
| Versionado | — | — | snapshot + puntero, append-only | 37 |
| Realtime | — | ws / WebSocket / coder | auth igual que REST, rooms, LWW | 38 |
C.2 Cómo leer la tabla
La columna derecha es el 80% del trabajo. Un senior en Node que lee Go no está “aprendiendo backend de nuevo” — está aprendiendo dónde Go pone el err y cómo se llaman sus paquetes. Las decisiones ya las tiene: parametrizar, transaccionar, auditar, testear, desplegar con compuertas.
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ó.
El framework decide menos de lo que crees. FastAPI no te obliga a usar Depends ni Express a usar middleware — pero la industria sí te obliga a validar, a autenticar una vez y a no dejar stack traces. El framework propone el mecanismo; tú mantienes el control.
Un middleware es un filtro en la cadena del request: pasa por él antes de llegar a tu handler. Auth es middleware — “verifica el token” vive una vez y protege todas las rutas, no se copia en cada una.
Un framework es un esqueleto de aplicación ya decidido: te da la estructura (rutas, validación, errores) y tú llenas la lógica. Diferencia con librería: la librería la llamas tú; el framework te llama a ti.
El lenguaje solo cambia la forma. Promise.all/gather/errgroup son la misma idea con tres acentos — como throw/raise/return err. Por eso el libro muestra los tres: para que veas que la idea sobrevive a la sintaxis.
return hace dos cosas a la vez: devuelve el resultado Y termina la función — lo que esté debajo nunca corre. return task = “aquí está el plato, salgo de la cocina”.
C.3 Mini reto
Agregar a la tabla un concepto que el libro no cubrió (ej. caché) y clasificarlo en las tres columnas.
Ejemplo resuelto — caché: del lenguaje, casi nada (quizá estructuras en memoria); del framework, un decorador/middleware opcional; de la industria: invalidar es lo difícil, medir antes de cachear, TTL + claves versionadas, Redis como pieza compartida entre instancias. Si tu fila pone “Redis” en la columna del lenguaje, vuelve al cap. 40: el producto no es del lenguaje — la decisión de cachear tampoco.
C.4 Vocabulario técnico del capítulo
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.
Asíncrono = empezar algo sin esperar sentado a que termine: pides la pizza (async) y sigues trabajando; cuando llega, te avisan. Lo opuesto a síncrono (esperar parado). Vital cuando la espera es larga: red, disco, bases de datos.
Una goroutine es el hilo ultraligero de Go: go f() lanza una función en paralelo gastando casi nada — se pueden tener millones. Es la superpotencia de Go: concurrencia como palabra del lenguaje.
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.
Una firma (HMAC) prueba que un mensaje es auténtico y no fue tocado: se calcula con un secreto sobre el contenido. Los webhooks la usan para que verifiques “esto realmente vino de Stripe”.
Un log es el diario del programa: qué pasó, cuándo, con qué request. Estructurado = en JSON con campos (request_id, user_id), para filtrar por máquina y no con los ojos.
Una variable de entorno es configuración que vive fuera del código: DATABASE_URL, JWT_SECRET. El mismo binario corre en dev y prod con distintas vars — los secretos nunca se escriben en el código.
Un secreto es un dato que no puede publicarse: contraseñas de BD, llaves de API, el secreto que firma los JWT. Viven en .env (fuera de git) o en un secret manager — nunca en el código ni en el repo.
El runtime es el motor que ejecuta tu código: Node.js es el runtime de JavaScript fuera del navegador; CPython es el de Python; Go compila a binario y el runtime va empaquetado dentro. Es “quien corre” lo que escribiste.
La memoria RAM es el escritorio de trabajo del programa: rápida, pero se borra al apagar. Los datos que deben sobrevivir van a disco o a la base de datos. Por eso let tasks = [] pierde todo al reiniciar.
El CPU es el cerebro que ejecuta instrucciones; cada núcleo puede ejecutar una cosa a la vez (por eso importan la concurrencia y los procesos paralelos). “CPU-bound” = el límite es el cálculo, no la espera.
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 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.
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.
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.
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.