Communitygithub.com

lguidolin/migraciones-sin-tiempo-de-inactividad

Úsalo al cambiar un esquema de base de datos donde los datos deben sobrevivir al cambio: agregar/eliminar/renombrar columnas, restricciones, índices o realizar backfills. Síntomas: una migración destructiva junto con un despliegue de código, una columna NOT NULL con backfill, un UPDATE que bloquea la tabla o un renombrado. Palabras clave: expand/contract, cambio paralelo, backfill, NOT VALID, CREATE INDEX CONCURRENTLY, graphile-migrate.

¿Qué es migraciones-sin-tiempo-de-inactividad?

Esta habilidad describe una disciplina de cambios de esquema que mantiene un sistema en funcionamiento durante un despliegue continuo (rolling deploy). Cuando se despliega una nueva versión de la aplicación, los pods antiguos y nuevos comparten la misma base de datos, por lo que el esquema debe ser compatible con ambas versiones simultáneamente. El enfoque principal se basa en el patrón Expand/Contract (o cambio paralelo), que divide cualquier modificación del esquema en tres versiones separadas: Expand (agregar el nuevo elemento de forma aditiva y compatible hacia atrás), Migrate (realizar backfill por lotes acotados, escritura dual si es necesario, y cambiar lecturas al nuevo esquema) y Contract (eliminar el elemento antiguo solo después de que la versión anterior esté completamente retirada). También cubre técnicas seguras para PostgreSQL, como agregar restricciones con `NOT VALID` y luego `VALIDATE`, crear índices con `CREATE INDEX CONCURRENTLY` (fuera de una transacción), y establecer `lock_timeout`/`statement_timeout` para evitar bloqueos. La habilidad es aplicable a cualquier proyecto que maneje datos que deban sobrevivir al despliegue (como staging con datos o producción) y está diseñada para usarse con herramientas como graphile-migrate.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/lguidolin/agent-skills/tree/main/skills/zero-downtime-migrations

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Migraciones Sin Tiempo de Inactividad

Resumen

Disciplina de cambios de esquema que mantiene un sistema en funcionamiento durante un despliegue continuo. Durante un despliegue, los pods antiguos y los nuevos comparten una misma base de datos — por lo que el esquema debe ser compatible con ambas versiones de la aplicación a la vez. Combinar una migración destructiva con el despliegue que la necesita es la clásica interrupción autoinfligida.

Reglas de Autoría (todos los proyectos)

  • Dos tipos de migración, mantenidos distintos: el conjunto current/ idempotente (iteración en desarrollo — se vuelve a ejecutar cada ciclo, CREATE OR REPLACE / IF NOT EXISTS, objetos en forma final, sin ALTER posterior a la creación) y las migraciones committed (inmutables, ordenadas, lo que realmente se despliega). ALTER DEFAULT PRIVILEGES es el único ALTER en línea aceptado.
  • La propiedad proviene de cómo se ejecutan las migraciones, no de ALTER ... OWNER dispersos.
  • Una única fuente de verdad de bootstrap compartida por la ruta de inicio local/Docker y la base de datos shadow/test — cada entorno se construye de forma idéntica.

Expand/Contract (Cambio Paralelo)

Se aplica cuando: la base de datos contiene datos que deben sobrevivir al despliegue (staging con datos, producción). Exento: proyectos locales/reiniciables — pero escribe las migraciones commit como si esto aplicara, para que la promoción nunca sea una reescritura.

Un cambio de esquema se divide en tres versiones, nunca en una:

  1. Expand — agrega la nueva forma de manera aditiva, compatible hacia atrás: nueva columna nullable, nueva tabla, nueva función. La versión N de la aplicación sigue funcionando sin cambios.
  2. Migrate — realiza backfill en lotes acotados (nunca un UPDATE que bloquee toda la tabla); escritura dual desde la app N+1 si es necesario; cambia las lecturas a la nueva forma. Solo ahora agrega NOT NULL (añade la restricción NOT VALID, luego VALIDATE por separado).
  3. Contract — solo después de que la versión N de la app esté completamente retirada, elimina la columna/restricción antigua en una versión posterior.

Trampas de PostgreSQL

TrampaEnfoque seguro
Columna NOT NULL con valor predeterminado volátil/grandeAgregar nullable → backfill en lotes → agregar restricción NOT VALID → VALIDATE
Agregar una restricciónAgregar NOT VALID primero, luego VALIDATE CONSTRAINT (bloqueo más débil)
Construir un índiceCREATE INDEX CONCURRENTLY — no se puede ejecutar dentro de una transacción; aíslalo del envoltorio de transacción de la herramienta de migración
Una migración bloqueada que congela producciónEstablece lock_timeout / statement_timeout para que falle rápidamente
Renombrar una columnaEs expand/contract: agregar nueva → backfill → cambiar lecturas → eliminar antigua, a través de versiones

Por qué "CREATE OR REPLACE en forma final" no es suficiente en producción

Esa regla es ergonomía para el desarrollador y es correcta en desarrollo. En producción, con usuarios en vivo y un despliegue continuo, ambas versiones de la aplicación comparten el esquema durante la duración del despliegue — por lo que expand/contract es lo que hace seguro el cambio. No confundas los dos conceptos.

Justificación completa: Artículo XVII de la constitución, incluido en engineering-constitution/references/engineering-constitution.md. Pipeline de despliegue: cloud-delivery-aks.

Individual skills in this repo

This repo contains 18 individual skills — each has its own dedicated page.

lguidolin/change-hygiene-and-code-craft

Use when writing or refactoring code, structuring a commit or PR, or deciding whether to abstract duplication. Symptoms — mixing reorg with logic changes, a PR doing several things at once, a file growing large, the second copy of similar code, or unsure whether to DRY something up.

lguidolin/cloud-delivery-aks

Use when deploying to Kubernetes or Azure Kubernetes Service (AKS), configuring cloud secrets, setting up progressive rollout/canary, per-PR ephemeral environments, or k8s health probes. Keywords — Kubernetes, AKS, Key Vault, Argo Rollouts, Flagger, canary, blue-green, liveness, readiness, PodDisruptionBudget, HPA, rollback, GHCR.

lguidolin/commit-history-rewrite

Use when an existing repository has messy commit history that needs to conform to conventional commits before adopting release-please, or when intermediate WIP/fixup/merge commits need to be cleaned up.

lguidolin/conventional-commits-and-releases

Use when committing, writing a commit message, opening a PR that will be squash-merged, or configuring automated versioning/changelogs. Keywords — conventional commits, release-please, semver, feat/fix/chore, breaking change, changelog.

lguidolin/defense-in-depth-security

Use when handling untrusted input, secrets, authentication/authorization, or dependencies — or threat-modeling a new surface. Keywords — STRIDE, threat model, least privilege, secrets management, supply chain, dependency scanning, input validation, audit log, defense in depth.

lguidolin/designing-before-building

Use when starting a feature, fixing a non-trivial bug, or about to write implementation code — before any code exists. Symptoms you need this: "this is simple, I'll just code it", reaching for the editor before a design is approved, or an idea that hasn't been turned into a spec and plan.

lguidolin/engineering-constitution

Use when starting work in a project that follows the engineering constitution, orienting to its rules, or deciding which engineering practice applies to a task — spec writing, commits, testing, security, deploys, database, or UI work.

lguidolin/graphql-contract-testing

Use when writing a GraphQL query/mutation that the UI and a test will share, or building route/schema contract or smoke tests. Symptoms — copying a query into a test, a test asserting on query text, schema change that didn't break the UI build, or RLS/permission drift. Keywords — graphql-codegen, typed document, contract test, route smoke test.

lguidolin/init-repo-CI

Use when setting up a new repository with conventional commits, release-please, and CI automation, or when retrofitting an existing repository that lacks automated versioning and PR validation workflows.

lguidolin/interface-craft-and-accessibility

Use when building or styling UI — components, layouts, forms, design tokens — or making accessibility decisions. Keywords — a11y, WCAG, keyboard navigation, focus state, contrast, design system, minimalist UI, component reuse, ARIA, semantic HTML.

lguidolin/merge-gates-and-automation

Use when setting up or changing CI, pre-push hooks, or a task runner, or deciding what must pass before merge. Symptoms — tempted to put authoritative checks only in a local hook, skip CI, bypass with --no-verify, or unsure what gates a merge vs. runs locally.

lguidolin/observability-and-slos

Use when adding logging, metrics, tracing, health checks, SLOs, or alerting — or when building a service surface that needs to be operable and debuggable. Keywords — structured logs, OpenTelemetry, correlation id, RED metrics, liveness, readiness, SLI, SLO, error budget, alerting.

lguidolin/performance-and-scale

Use when working on hot paths, list endpoints, pagination, data-access in loops, or public interfaces/schemas. Symptoms — unbounded queries, N+1 access, no latency budget, optimizing without measuring, or changing an interface many consumers depend on. Keywords — pagination, N+1, Hyrum's Law, performance budget, bundle size.

lguidolin/postgres-postgraphile-rls-and-sql

Use when writing PostgreSQL, PostGraphile config, Row-Level Security policies, SQL schema files, or working on the Browser→App→PostGraphile→Postgres data path. Keywords — RLS, SECURITY DEFINER, search_path, pgSettings, grants, roles, GraphQL depth limit, query cost, statement_timeout, SQL file organization.

lguidolin/recording-decisions

Use when a design or architecture decision has been made and needs to be captured — writing a decision record or ADR, updating a decision index, noting a deferred idea, or superseding a past decision. Keywords — ADR, decision record, rationale, rejected alternatives, dependency index.

lguidolin/resilience-and-deploy-safety

Use when planning a deploy, designing a rollback, or responding to an incident or writing a postmortem. Keywords — deploy safety, rollback, immutable artifact, progressive delivery, canary, blast radius, incident response, blameless postmortem, error budget.

lguidolin/ship-it

Use when the user wants to ship work — push, PR, archive decision records, merge, and clean up. Handles the full lifecycle from committing final changes through post-merge cleanup including converting specs/plans to compact decision records.

lguidolin/tests-as-a-control

Use when writing or modifying tests, when a test breaks during a refactor, or when testing permission/role rules. Symptoms — tempted to edit a test to make it pass, testing only the happy path, a deny-test that started passing, flaky tests, or unsure what to assert.

Skills relacionados