Migracion de esquema sin downtime
Un ALTER TABLE sobre una tabla caliente bloquea la aplicacion entera; expand-contract reparte el mismo trabajo en lotes que nadie nota.
📈 Que cambia para el negocio
Permite cambiar el esquema de una tabla caliente sin ventana de mantenimiento ni 503 para el usuario final.
💼 Que demuestra tecnicamente
Muestra que el trabajo total de una migracion no cambia — lo que cambia es si se cobra junto con la app caida o repartido — y que el healthcheck en verde puede tapar 22 minutos de indisponibilidad.
✅ Evidencia que deja
- Contrasta /migrate-blocking y /migrate-expand-contract con availability_pct medida DURANTE la migracion.
- Hace visible longest_single_lock_ms: la metrica que decide si la app se cae, distinta del tiempo total.
- Expone /migration/state con la fase actual, el progreso del backfill y el estado del feature flag.
👀 Que mirar al ejecutarlo
- Si readers_failed es mayor que cero en la variante bloqueante y exactamente cero en la corregida.
- Si longest_single_lock_ms baja de la duracion entera de la migracion a la de un solo lote.
- Si lock_held_ms total es parecido en las dos: el trabajo no desaparece, se reparte.
Como esta resuelto en cada stack
Expand-contract en cuatro fases con el read-write lock de cada runtime: flock LOCK_SH/LOCK_EX del sistema operativo en PHP — el unico que coordina procesos y no hilos —, RWLock construido a mano sobre Condition en Python porque la stdlib no lo trae, el event loop COMO lock en Node, ReentrantReadWriteLock en modo justo con tryLock(timeout) en Java, ReaderWriterLockSlim con TryEnterReadLock(ms) en .NET, sync.RWMutex con deadline armado por goroutine en Go, y RwLock con spin acotado en Rust — el unico caso del lab donde su respuesta es peor que la de los otros seis
| Stack | Health check local | Compose | Detalle |
|---|---|---|---|
| 🐘 PHP 8.3 | http://localhost:8100/17/health | compose.root.yml | README del stack |
| 🐍 Python 3.12 | http://localhost:8200/17/health | compose.python.yml | README del stack |
| 🟢 Node.js 22 | http://localhost:8300/17/health | compose.nodejs.yml | README del stack |
| ☕ Java 21 | http://localhost:8400/17/health | compose.java.yml | README del stack |
| 🔵 .NET 8 | http://localhost:8500/17/health | compose.dotnet.yml | README del stack |
| 🐹 Go 1.23 | http://localhost:8600/17/health | compose.go.yml | README del stack |
| 🦀 Rust 1.83 | http://localhost:8700/17/health | compose.rust.yml | README del stack |
El expediente completo
El caso no empieza en el codigo: empieza en el sintoma y termina en el postmortem.