Un handler que lanza una excepción con ciertos inputs pierde una conexión a la base de datos por cada request fallido. Después de treinta, el pool queda vacío y requests sanos empiezan a morir con timeouts. Por qué la limpieza va en finally, y dónde ponerla para que nadie tenga que acordarse.
Una nueva serie con un formato distinto: posts cortos, una práctica de bases de datos en cada uno, todas sacadas de cosas que de verdad se rompen bajo carga. Fugas de conexiones, N+1 invisibles, migraciones que bloquean tablas, tasks que corren contra datos que todavía no existen.
Los scanners de la parte 12 te dicen qué dependencias son vulnerables, pero los upgrades siguen siendo manuales y nunca alcanzan. Renovate self-hosted como pipeline programado, los dos tokens que lo mantienen vivo y el chequeo previo que convirtió una sesión recurrente de debugging en una línea de log.
El escaneo de seguridad tarda 21 minutos, inunda cada merge request con hallazgos sobre código que nadie tocó y el equipo aprende a pasarlo de largo. SAST diff-aware con Semgrep, un umbral de severidad para OSV-Scanner y el formato de reporte que devuelve los hallazgos al widget del MR.
La suite de E2E es demasiado lenta y demasiado inestable para bloquear merges, pero la señal la necesitas igual, junto con un lugar donde ver su historial. Pipelines programados, service tokens para un entorno con puerta de acceso, sharding de Playwright y un archivo de reportes que sobrevive a sus pipelines.
Un job de release que hace push del commit de versiones dispara un pipeline nuevo, y dos merges seguidos compiten entre sí por publicar en npm. Cómo serializar releases con resource_group, autenticar el push desde un job, y cuándo usar [skip ci] frente a -o ci.skip.
Cincuenta paquetes y ocho apps en un solo repo: recompilar el mundo en cada commit no es una opción. Detección de cambios con rules:changes y compare_to, un anchor de YAML por app, un task runner que ya conoce el grafo de dependencias, y la semana en que los runners se quedaron sin disco.
Diez repos hermanos copiaron y pegaron las mismas ~300 líneas de YAML, y cada copia se fue rompiendo por su lado. include:, hidden jobs como API pública, un vocabulario de rules con !reference, y cómo publicar cambios cuando todos los consumidores siguen main.
Mergear un cambio del frontend debería correr los tests E2E que viven en otro repo, mantenido por otro equipo. Trigger jobs, pipelines multi-project frente a parent-child, cómo reflejar el estado del pipeline hijo, y un allowlist de variables que además funciona como frontera de secretos.
Haz push a una rama con un merge request abierto y aparecen dos pipelines para el mismo commit: el doble de costo y dos estados que interpretar. Los tipos de pipeline, workflow rules como portero, y lo que de verdad cuesta correr solo branch pipelines.
Cada job corre en cada push: los jobs de deploy se cuelan en las ramas de feature y las suites caras corren aunque nada relevante haya cambiado. Rules a nivel de job (if, changes, exists), gates manuales y un regex que coincidía en silencio con casi cualquier mensaje de commit.
Tus jobs son eficientes pero tu pipeline es lento, porque los stages obligan a cada job a esperar a jobs de los que no depende. Cómo reemplazar las barreras de stage por un grafo con needs, y partir el job más lento entre varios runners con parallel.
Tu job de deploy recompila la app que otro job acaba de compilar. Meter dist/ al cache parece la solución, hasta que despliega código viejo sin avisar. Artifacts, expiración, reportes de fallos y cómo pasar valores entre jobs con dotenv.
Un cache que funciona todavía pierde tiempo de tres formas: cada job lo vuelve a subir, un bump del lockfile arranca de cero, y los merge requests nunca ven lo que main dejó caliente. Políticas de cache, fallback keys y el cache partido de las ramas protegidas.
Una guía desde cero de .gitlab-ci.yml: jobs, stages, runners, variables y un cache de dependencias basado en el lockfile. Incluye la trampa del cache en runners self-hosted que nos costó 90 segundos por job a cambio de nada.
Crear una regla de ESLint personalizada para prohibir el uso de un componente. Cómo recorrer el AST, identificar el nodo correcto y empaquetar la regla en un plugin local.
Cómo usar @aws-sdk/client-s3 para subir archivos y carpetas enteras a AWS S3 desde Node.js, con los gotchas más comunes (content type, claves con barras, paths de Windows).
Una colección de snippets de GORM que tengo a mano cuando arranco un proyecto en Go — instalación, modelos, validaciones, relaciones many-to-many, hooks y consultas más comunes.
Aprendizajes de mis primeros tres años como Frontend Developer en Crehana — fallar rápido, creer en lo que construyes y por qué las personas son lo más importante.
Cómo conectar webpack-dev-server a un proyecto Django para tener hot module replacement, incluyendo un template tag para alternar entre desarrollo y producción.
Por qué los tests de controladores muchas veces prueban lo que Rails ya garantiza, y cómo los feature tests con RSpec y Capybara permiten testear lo que el usuario realmente ve.