Actualizas la página. El banner sigue ahí. Tu página de inicio está caída, tu jefe pregunta si “internet está roto” y WordPress insiste alegremente en que está “brevemente no disponible”.
Ese mensaje debería durar segundos. Cuando se queda, casi nunca es misterioso. Es un archivo de bloqueo muy simple, una actualización fallida o un problema de permisos/almacenamiento disfrazado. Trátalo como un incidente: verifica impacto, identifica el mecanismo que bloquea, restaura el servicio y luego arregla las condiciones que lo provocaron.
Qué significa realmente el mensaje de mantenimiento
El modo de mantenimiento de WordPress no es un “modo” en el sentido moderno de feature-flag. Es un bloqueo basado en archivo.
Durante una actualización (core, plugin, tema, traducciones), WordPress crea un archivo llamado .maintenance en la raíz del sitio (el mismo directorio que wp-config.php).
Mientras ese archivo exista y aparezca “lo bastante reciente”, WordPress corta el flujo normal de renderizado de páginas y devuelve el mensaje de mantenimiento.
El diseño es deliberadamente burdo. Actualizar código en disco mientras hay solicitudes ejecutando PHP es un campo minado. El archivo de bloqueo es la forma en que WordPress dice:
“Aléjense. Estoy cambiando piezas.”
El modo de mantenimiento debería borrarse automáticamente al final de una actualización exitosa. Cuando no lo hace, el archivo de bloqueo permanece, o WordPress sigue pensando que hay una actualización en progreso porque algo más está atascado: un paquete medio extraído, un problema de permisos, disco lleno, una respuesta en caché o un proceso PHP que murió a mitad de camino.
El mensaje es honesto en una cosa: realmente ocurre durante mantenimiento programado. La mentira es “brevemente”.
Cómo WordPress decide mostrar el mensaje
A alto nivel, WordPress hace esto:
- Crea
.maintenancecon una marca de tiempo. - Ejecuta el proceso de actualización (descarga, descompresión, copia, quizá ejecutar actualizaciones de BD).
- Elimina
.maintenancecuando termina.
Si el proceso de actualización se interrumpe—timeout HTTP, error fatal de PHP, fallo de escritura en el sistema de archivos, worker matado, crash, o un humano que hace clic en “Actualizar todo” y cierra la pestaña a mitad de la petición—el paso de limpieza puede no llegar a ejecutarse.
Broma #1: El modo de mantenimiento de WordPress es como un cartel de “No molestar”: genial hasta que el servicio de limpieza no vuelve y te quedas con las toallas de ayer.
Hechos interesantes y un poco de historia (porque importa)
Si ejecutas WordPress en producción, ayuda conocer qué supuestos hay metidos en sus mecanismos de actualización y bloqueo. Aquí tienes hechos concretos que explican por qué este problema sigue apareciendo en 2025:
- El bloqueo es un archivo, no un flag en la base de datos. Esa elección viene de la simplicidad de las primeras épocas de WordPress: se asumía que escribir en el sistema de archivos era más barato que cambiar el esquema y seguro en hosting compartido.
- Las actualizaciones automáticas en segundo plano llegaron en WordPress 3.7 (2013). Antes de eso, la mayoría de actualizaciones eran manuales e interactivas, por lo que las fallas se notaban más rápido—por humanos molestos.
- El mensaje de mantenimiento es intencionalmente genérico. Evita exponer detalles internos a usuarios no autenticados, lo cual es buena higiene de seguridad y mala ergonomía para operadores.
- Las actualizaciones del core usan un estilo de “copiar y luego intercambiar”. WordPress intenta reducir estados de medio-actualizado, pero los plugins/temas aún son vulnerables a directorios medio escritos si el proceso se interrumpe.
- Existe lógica de credenciales de sistema de archivos porque muchos sitios no pueden escribir en sus propios directorios. Ese legado del hosting compartido basado en FTP aún influye en cómo fallan las actualizaciones (solicitudes de credenciales, incapacidad para escribir, fallos parciales silenciosos).
- Las actualizaciones de traducciones son una vía de actualización propia. También pueden disparar el modo mantenimiento, incluso cuando juraste “no cambiamos nada”.
- Las cachés de objetos y de página pueden vivir más tiempo que el bloqueo. Puedes borrar
.maintenancey seguir mostrando el banner si una caché upstream decidió que ese mensaje es “contenido”. - Los despliegues blue/green hicieron esto menos frecuente—hasta que la gente volvió a actualizar nodos en vivo. En entornos contenerizados, actualizar en disco dentro de un contenedor en ejecución es el equivalente moderno de editar producción con vim.
- Algunos hosts implementan sus propios conmutadores de “mantenimiento”. Plataformas gestionadas pueden presentar el mismo mensaje mediante reglas de proxy, no por WordPress.
Guion de diagnóstico rápido (primero/segundo/tercero)
Quieres el camino más corto a “sitio de vuelta” sin crear un incidente más interesante. Aquí está el orden que funciona cuando estás de guardia y tu café aún llega.
Primero: confirma si es WordPress o el edge mintiéndote
- Evita las cachés y prueba directamente el origen (o al menos con cabeceras que rompan la caché).
- Si el banner persiste solo a través del CDN/WAF pero no en el origen, esto es un incidente de caché, no de WordPress.
Segundo: busca .maintenance y su marca de tiempo
- Si
.maintenanceexiste y es antiguo, elimínalo y vuelve a probar. - Si es reciente y las actualizaciones están realmente en curso, no quites el archivo a ciegas—verifica que el proceso de actualización no esté aún copiando archivos.
Tercero: encuentra la actualización que falló y por qué
- Revisa los logs de error de PHP-FPM/Apache/Nginx buscando fatales/timeouts durante la actualización.
- Revisa espacio en disco y agotamiento de inodos (sí, los inodos todavía arruinan días).
- Revisa permisos/propiedad: ¿puede el usuario PHP escribir en
wp-contenty (durante core) en la raíz de WordPress? - Revisa artefactos atascados en
wp-content/upgrade.
Por qué se queda atascado: los verdaderos modos de fallo
1) El archivo .maintenance nunca se eliminó
El caso más común. Una petición expiró, un worker de PHP murió, alguien navegó fuera o el servidor web se reinició a mitad de la actualización.
WordPress no tiene un conserje en segundo plano que limpie de forma fiable tras una interrupción catastrófica.
Si eliminas el archivo y todo carga, no “arreglaste” la actualización—quitaste el bloqueo. A veces eso es suficiente. A veces simplemente desbloqueaste a los usuarios dejando un plugin medio actualizado que fallará después.
2) Actualización parcial: directorio de plugin/tema en estado roto
Las actualizaciones pueden dejar:
- Una carpeta de plugin sin archivos críticos (autoloaders, archivo principal del plugin).
- Una nueva versión extraída en un directorio temporal pero no movida a su lugar.
- Una mezcla de archivos antiguos y nuevos por fallos de permisos a mitad de la copia.
Eliminar .maintenance puede simplemente revelar el verdadero problema: errores fatales, pantallas en blanco o bucles de login en el admin.
3) Desajuste de permisos/propiedad del sistema de archivos
Las actualizaciones de WordPress necesitan acceso de escritura. En muchos servidores, el código es propiedad de un usuario de despliegue (o root), pero PHP corre como www-data (o similar).
Las actualizaciones entonces fallan a mitad: el zip descargado existe, la extracción falla, la limpieza nunca se ejecuta y .maintenance permanece.
4) Problemas de almacenamiento: disco lleno, inodos llenos, I/O lento o fallos de almacenamiento en red
Como ingeniero de almacenamiento: aquí es donde muere la parte de “brevemente”.
Las actualizaciones son intensivas en escrituras: descargar, descomprimir (muchos archivos pequeños), renombrar, eliminar.
Si tu disco está lleno, o tu tabla de inodos está agotada, o tu backend NFS/EFS/SMB está teniendo un momento, la actualización puede colgar o fallar en un paso aleatorio.
5) Capas de caché siguen sirviendo el banner después de arreglarlo
CDNs, proxies inversos y plugins de caché de WordPress pueden cachear la respuesta de mantenimiento como si fuera una página válida.
El origen está sano, pero el edge sigue repitiendo la mala noticia.
6) Actualizaciones concurrentes o estampidas de “Actualizar todo”
Varios admins haciendo clic en actualizar al mismo tiempo es un generador de caos subestimado.
Incluso con un bloqueo de mantenimiento, puedes obtener intentos superpuestos que dejan directorios temporales y estados inconsistentes.
7) “Modo mantenimiento” del host gestionado o actualizaciones de la plataforma
Algunas plataformas muestran el mismo mensaje mientras hacen snapshots, migraciones o parches. En ese caso, eliminar .maintenance no ayudará porque WordPress no es quien lo está emitiendo.
Tareas prácticas con comandos: diagnosticar, decidir, arreglar
A continuación hay tareas reales que puedes ejecutar en un host Linux típico. Cada una incluye: el comando, qué significa la salida y qué decisión tomar.
Ajusta las rutas a tu docroot. Asume que la raíz de WordPress es /var/www/example.com/public.
Task 1: Confirmar que ves el origen, no una respuesta cacheada del edge
cr0x@server:~$ curl -sS -D- -o /dev/null -H 'Cache-Control: no-cache' https://example.com/ | sed -n '1,20p'
HTTP/2 503
date: Sat, 27 Dec 2025 12:01:11 GMT
content-type: text/html; charset=UTF-8
cache-control: no-cache, must-revalidate, max-age=0
server: nginx
Qué significa: HTTP 503 es consistente con el modo de mantenimiento de WordPress. Si vieras cabeceras como x-cache: HIT o cabeceras específicas de CDN, sospecharías caché.
Decisión: Si la respuesta es 503 también en el origen, procede a comprobaciones del lado del servidor. Si el origen es 200 pero el edge es 503, purga/bannea la caché y revisa las reglas del CDN.
Task 2: Comprobar si existe .maintenance (y dónde)
cr0x@server:~$ sudo -u www-data bash -lc 'cd /var/www/example.com/public && ls -la .maintenance || echo "no .maintenance"'
-rw-r--r-- 1 www-data www-data 55 Dec 27 11:43 .maintenance
Qué significa: El archivo existe y es legible. Su mera presencia puede activar el banner.
Decisión: Revisa la frescura de la marca de tiempo a continuación. Si es antiguo, normalmente puedes eliminarlo. Si es reciente, confirma si una actualización está corriendo activamente.
Task 3: Inspeccionar el contenido de .maintenance
cr0x@server:~$ sudo -u www-data bash -lc 'cd /var/www/example.com/public && cat .maintenance'
<?php $upgrading = 1766835803; ?>
Qué significa: Almacena una marca de tiempo UNIX. WordPress usa esto para decidir si el bloqueo está “obsoleto”.
Decisión: Conviértelo a hora humana y compáralo con el ahora.
Task 4: Convertir la marca de tiempo de actualización y juzgar si está obsoleta
cr0x@server:~$ date -d @1766835803
Sat Dec 27 11:43:23 UTC 2025
Qué significa: Ahora sabes cuándo empezó el mantenimiento.
Decisión: Si fue hace más de 30 minutos y no hay actualizaciones en curso, trátalo como atascado y elimina el archivo después de revisar los logs por fallos.
Task 5: Comprobar si hay un proceso de actualización activo (workers PHP-FPM, unzip, wp-cli)
cr0x@server:~$ ps aux | egrep 'wp-cli|wordpress|unzip|php.*(update|upgrade)' | grep -v egrep
www-data 21904 0.2 1.1 312000 46000 ? S 11:42 0:02 php-fpm: pool www
Qué significa: No hay nada obvio corriendo además de workers PHP normales.
Decisión: Es seguro asumir que la actualización no está en vuelo. Pasa a la limpieza: elimina el bloqueo y luego valida la integridad.
Task 6: Eliminar .maintenance de forma segura y volver a probar
cr0x@server:~$ sudo -u www-data bash -lc 'cd /var/www/example.com/public && rm -v .maintenance'
removed '.maintenance'
Qué significa: El bloqueo ha desaparecido.
Decisión: Vuelve a probar el sitio y el admin inmediatamente. Si carga, aún debes confirmar que las actualizaciones no dejaron el código medio roto.
Task 7: Comprobar el directorio de trabajo de upgrade que indica actualizaciones interrumpidas
cr0x@server:~$ sudo -u www-data bash -lc 'cd /var/www/example.com/public && ls -la wp-content | sed -n "1,60p"'
total 64
drwxr-xr-x 9 www-data www-data 4096 Dec 27 11:42 .
drwxr-xr-x 5 www-data www-data 4096 Dec 27 11:40 ..
drwxr-xr-x 2 www-data www-data 4096 Dec 27 11:42 upgrade
drwxr-xr-x 36 www-data www-data 4096 Dec 27 11:10 plugins
drwxr-xr-x 8 www-data www-data 4096 Dec 27 10:55 themes
Qué significa: Existe el directorio upgrade. Eso es normal durante actualizaciones; es sospechoso cuando se queda lleno de residuos.
Decisión: Inspecciónalo. Si contiene extractos parciales de hace horas, límpialo tras confirmar que no hay actualizaciones en curso.
Task 8: Inspeccionar el contenido de wp-content/upgrade
cr0x@server:~$ sudo -u www-data bash -lc 'cd /var/www/example.com/public && find wp-content/upgrade -maxdepth 2 -type f | head'
wp-content/upgrade/temp-backup/plugin-akismet.1766835740.zip
wp-content/upgrade/akismet/akismet.php
Qué significa: Tienes artefactos sobrantes. No siempre son dañinos, pero señalan que la ruta de actualización no terminó limpamente.
Decisión: Si el sitio está estable, puedes eliminar contenido temporal de upgrade obsoleto para evitar colisiones futuras y recuperar espacio.
Task 9: Comprobar espacio en disco (las actualizaciones fallan cuando te quedas sin espacio)
cr0x@server:~$ df -h /var/www/example.com/public
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 40G 39G 300M 99% /
Qué significa: Uso del 99%. Las actualizaciones necesitan espacio libre para descargas y extracciones. 300MB es “a un plugin de la vergüenza”.
Decisión: Libera espacio antes de reintentar actualizaciones. Si no, repetirás el incidente.
Task 10: Comprobar agotamiento de inodos (el asesino silencioso de operaciones con muchos archivos pequeños)
cr0x@server:~$ df -i /var/www/example.com/public
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda1 2621440 2621200 240 100% /
Qué significa: Tienes prácticamente cero inodos. Descomprimir actualizaciones de WordPress crea miles de archivos; el agotamiento de inodos hace que “escribir” falle incluso cuando queda espacio.
Decisión: Encuentra y borra basura que use muchos inodos (directorios de caché, backups antiguos, archivos temporales). Luego reintenta las actualizaciones.
Task 11: Comprobar propiedad y permisos de archivos en la raíz de WordPress
cr0x@server:~$ sudo bash -lc 'cd /var/www/example.com/public && stat -c "%U:%G %a %n" wp-config.php wp-content wp-admin | sed -n "1,10p"'
root:root 640 wp-config.php
root:root 755 wp-content
root:root 755 wp-admin
Qué significa: Todo es propiedad de root. Si PHP corre como www-data, WordPress no puede escribir actualizaciones a menos que hayas configurado métodos de sistema de archivos/ACLs.
Decisión: Decide tu modelo operativo: o (a) desplegar de forma inmutable y hacer actualizaciones via CI/CD, o (b) permitir que WordPress escriba corrigiendo propiedad/ACLs. No hagas ambas cosas a medias.
Task 12: Verificar el usuario runtime de PHP y si puede escribir
cr0x@server:~$ ps -o user,group,comm -C php-fpm8.2 2>/dev/null | head
USER GROUP COMMAND
root root php-fpm8.2
www-data www-data php-fpm8.2
Qué significa: Los workers corren como www-data.
Decisión: Asegura que www-data tenga permisos de escritura donde ocurren las actualizaciones (comúnmente wp-content y a veces la raíz para actualizaciones del core). Si no puedes permitir eso, deja de hacer actualizaciones en sitio.
Task 13: Ejecutar WP-CLI para comprobar integridad del core y actualizaciones pendientes
cr0x@server:~$ sudo -u www-data bash -lc 'cd /var/www/example.com/public && wp core verify-checksums'
Success: WordPress installation verifies against checksums.
Qué significa: Los archivos del core coinciden con los checksums esperados para tu versión. Buena señal de que el core no se quedó medio actualizado.
Decisión: Si esto falla, planifica reinstalar archivos del core (sin tocar wp-content) o redeplegar desde un artefacto conocido y bueno.
Task 14: Identificar qué se estaba actualizando cuando se quedó atascado
cr0x@server:~$ sudo -u www-data bash -lc 'cd /var/www/example.com/public && wp plugin list --update=available'
+-------------------+----------+-----------+---------+
| name | status | update | version |
+-------------------+----------+-----------+---------+
| akismet | active | available | 5.3 |
| woocommerce | active | available | 8.4.0 |
+-------------------+----------+-----------+---------+
Qué significa: Hay actualizaciones disponibles; el atasco probablemente ocurrió durante una de estas (o durante actualizaciones de core/tema).
Decisión: No pulses “actualizar todo” otra vez. Actualiza un componente a la vez tras estabilizar disco/permisos, y vigilando los logs.
Task 15: Revisar errores recientes de PHP que suelen coincidir con actualizaciones fallidas
cr0x@server:~$ sudo tail -n 60 /var/log/php8.2-fpm.log
[27-Dec-2025 11:42:19] WARNING: [pool www] child 22001 said into stderr: "PHP Fatal error: Uncaught Error: Class 'Automattic\WooCommerce\Internal\DependencyManagement\Container' not found in /var/www/example.com/public/wp-content/plugins/woocommerce/woocommerce.php:45"
[27-Dec-2025 11:42:19] WARNING: [pool www] child 22001 said into stderr: "PHP Stack trace: #0 {main} thrown in /var/www/example.com/public/wp-content/plugins/woocommerce/woocommerce.php on line 45"
Qué significa: Un plugin está en estado roto (clase faltante). Eso es un clásico de actualización parcial: algunos archivos se movieron y otros no.
Decisión: Restaura ese directorio de plugin desde una versión conocida y buena (backup/artefacto), o reinstálalo via WP-CLI. No borres archivos al azar.
Task 16: Reinstalar un plugin roto limpiamente (sin adivinar)
cr0x@server:~$ sudo -u www-data bash -lc 'cd /var/www/example.com/public && wp plugin deactivate woocommerce && wp plugin install woocommerce --force --activate'
Plugin 'woocommerce' deactivated.
Installing WooCommerce (9.1.0)
Downloading installation package from https://downloads.wordpress.org/plugin/woocommerce.9.1.0.zip...
Unpacking the package...
Installing the plugin...
Plugin installed successfully.
Activating 'woocommerce'...
Plugin 'woocommerce' activated.
Success: Installed 1 of 1 plugins.
Qué significa: Reemplazaste los archivos del plugin con un conjunto coherente y lo reactivaste.
Decisión: Vuelve a probar flujos críticos (checkout, login, admin). Si es un plugin de ingresos, no asumas que “activado” significa “saludable”.
Task 17: Revisar los logs de error del servidor web por fallos de permisos/rename durante la actualización
cr0x@server:~$ sudo tail -n 80 /var/log/nginx/error.log
2025/12/27 11:42:18 [error] 21011#21011: *4411 FastCGI sent in stderr: "PHP message: PHP Warning: rename(/var/www/example.com/public/wp-content/plugins/akismet,/var/www/example.com/public/wp-content/plugins/akismet.old): Permission denied" while reading response header from upstream, client: 203.0.113.50, server: example.com, request: "POST /wp-admin/update.php?action=upgrade-plugin HTTP/2.0"
Qué significa: WordPress intentó renombrar directorios como parte de la actualización y recibió Permission denied.
Decisión: Arregla la propiedad/ACLs y luego reintenta las actualizaciones. Si no, fallarán siempre, normalmente en el paso de rename.
Task 18: Corregir la propiedad para un modelo “WordPress se actualiza solo” (opinión, pero común)
cr0x@server:~$ sudo chown -R www-data:www-data /var/www/example.com/public/wp-content
Qué significa: Ahora PHP puede escribir en wp-content. (Puede que también necesites acceso de escritura a la raíz para actualizaciones del core, según cómo operes.)
Decisión: Si usas despliegues inmutables, no hagas esto. En su lugar, desactiva actualizaciones desde el panel y sube cambios vía pipeline.
Task 19: Vaciar cachés que puedan estar repitiendo la página de mantenimiento
cr0x@server:~$ sudo -u www-data bash -lc 'cd /var/www/example.com/public && wp cache flush'
Success: The cache was flushed.
Qué significa: Caché de objetos de WordPress borrada (funciona con algunos backends de caché; varía).
Decisión: Si tienes una caché de página separada (Nginx FastCGI cache, Varnish, CDN), púrguela también. Si no puedes purgarla, al menos evita la caché y confirma la salud del origen.
Task 20: Validar estado HTTP y cuerpo después de las reparaciones
cr0x@server:~$ curl -sS -D- -o /dev/null https://example.com/ | sed -n '1,15p'
HTTP/2 200
date: Sat, 27 Dec 2025 12:09:07 GMT
content-type: text/html; charset=UTF-8
server: nginx
Qué significa: Has vuelto a 200 OK.
Decisión: El incidente no ha terminado hasta que confirmes que páginas clave y acciones de administración están saludables, y que has tratado la causa subyacente (espacio, permisos, proceso de actualización).
Tres microhistorias corporativas desde las trincheras
Microhistoria 1: El incidente causado por una suposición equivocada
Una empresa mediana ejecutaba WordPress detrás de un CDN y un WAF, con un clúster de origen separado. Marketing programó una “pequeña actualización de plugin” quince minutos antes de un anuncio de producto.
Alguien vio el banner de mantenimiento e hizo lo que dice Internet: eliminó .maintenance en un nodo de origen. El banner siguió.
La suposición equivocada fue sutil: asumieron que el banner se generaba en el origen en el momento del refresh. No era así. El CDN había cacheado la respuesta 503 de mantenimiento durante un tiempo sorprendentemente largo por una regla de edge destinada a proteger el origen durante caídas. Trató el 503 como cacheable “para reducir carga”.
Mientras tanto, la actualización había tenido éxito en dos nodos y fallado en uno. Así la flota quedó en estado split-brain: algunos nodos servían el plugin actualizado, un nodo tenía un directorio parcial y lanzaba fatales, y el edge reproducía felizmente la página de mantenimiento desde la caché.
La solución no fue heroica. Purgaron la caché del CDN para las rutas afectadas, sacaron el nodo roto de rotación, reinstalaron el plugin coherentemente y solo entonces reintrodujeron el nodo.
Pero la lección quedó: cuando ves un mensaje genérico, no puedes asumir dónde se generó. Verifica la capa primero.
Su acción post-incidente fue simple y efectiva: hacer que las respuestas 503 no sean cacheables en el edge salvo que estén explícitamente en una lista blanca, y añadir una comprobación de “bypass al origen” en el runbook de guardia.
Microhistoria 2: La optimización que salió mal
Otra organización decidió “acelerar” WordPress moviendo wp-content a almacenamiento en red para que varios web heads compartieran uploads y plugins. Funcionó bien con tráfico normal.
Las actualizaciones, sin embargo, se volvieron una ruleta.
El día de la actualización, se descargaba un zip del plugin, empezaba la extracción y luego el sistema de archivos se atascaba por segundos seguidos. Los picos de latencia de NFS hacían que los renames de directorio y operaciones de metadatos tardaran tanto que las peticiones PHP alcanzaban timeouts.
WordPress moría a mitad de la actualización, dejando .maintenance y un directorio de plugin medio movido.
El equipo intentó compensar aumentando timeouts de PHP y añadiendo reintentos. Eso hizo al sitio “más tolerante” pero también hizo las fallas más lentas y difíciles de detectar. Los usuarios permanecían más tiempo en modo mantenimiento. Los de guardia permanecían más tiempo en reuniones. Todos perdieron.
La solución aburrida fue dejar de optimizar lo equivocado: movieron el código de plugin/tema de vuelta al disco local en cada nodo y mantuvieron solo uploads en almacenamiento compartido. Las despliegues sincronizaban cambios de plugins entre nodos usando artefactos.
Las actualizaciones dejaron de quedarse atascadas porque la ruta crítica de actualización ya no dependía de costosas llamadas de metadatos en un sistema de archivos de red.
Cuando la gente dice “el almacenamiento es lento”, normalmente quieren decir “los metadatos son lentos”. Las actualizaciones de WordPress son mayormente operaciones de metadatos disfrazadas de zip.
Microhistoria 3: La práctica aburrida pero correcta que salvó el día
Una compañía con un WordPress fuertemente personalizado tenía un proceso de release estricto: staging primero, luego producción, con actualizaciones impulsadas por WP-CLI y una verdadera ruta de rollback.
Nadie podía hacer clic en “Actualizar” en producción, lo que hacía que la interfaz de administración fuera menos emocionante. Internet sobrevivió.
Una tarde, actualizaciones automáticas de traducción activaron brevemente el modo de mantenimiento, luego el sitio volvió a la normalidad. Minutos después, las tasas de error subieron en el monitoreo—no por el modo mantenimiento, sino por un conflicto en el autoloader de un plugin que solo se manifestaba bajo cierto estado de caché.
Como tenían logs, métricas y un artefacto conocido y bueno, no empezaron a “arreglar” producción a mano. Revirtieron al artefacto previo en todos los nodos, desactivaron el canal de actualización automática que introdujo el cambio y restauraron el servicio de forma coherente.
Luego reprodujeron el problema en staging y lo arreglaron correctamente.
Su gran victoria no fue un comando ingenioso. Fue disciplina: una fuente única de verdad para el código, despliegues repetibles y la capacidad de revertir sin negociar con un directorio de plugin medio escrito.
Broma #2: La estrategia de actualización de WordPress más fiable sigue siendo “no hacer cirugía en vivo”, que también es mi consejo para la mayoría de pasatiempos.
Errores comunes: síntoma → causa raíz → solución
Esta es la parte donde dejas de adivinar. Empareja tu síntoma con una causa probable y aplica la solución específica.
1) Síntoma: El banner de mantenimiento tarda horas; el sitio devuelve 503
- Causa raíz: Archivo
.maintenanceobsoleto dejado tras una actualización interrumpida. - Solución: Elimina
.maintenancede la raíz de WordPress; luego verifica la integridad de plugin/tema/core y los logs para encontrar qué falló.
2) Síntoma: El banner desaparece tras borrar .maintenance, pero ahora obtienes pantalla blanca (500)
- Causa raíz: Actualización parcial de plugin/tema causando un error fatal de PHP.
- Solución: Revisa logs de PHP, luego reinstala o restaura el plugin/tema roto. Usa WP-CLI cuando sea posible. No “borres carpetas al azar hasta que funcione”.
3) Síntoma: Algunos usuarios ven el banner, otros no
- Causa raíz: CDN o proxy inverso cacheando la respuesta de mantenimiento; o múltiples nodos de origen con estado inconsistente.
- Solución: Prueba el origen directamente, purga cachés y asegúrate de que todos los nodos tengan código consistente. Saca de rotación los nodos rotos.
4) Síntoma: Las actualizaciones siempre fallan y el modo mantenimiento se queda a menudo
- Causa raíz: Desajuste de permisos/propiedad; el usuario PHP no puede renombrar/escribir directorios.
- Solución: Elige un modelo: o permites que WordPress escriba (propiedad/ACLs) o deshabilitas actualizaciones desde el panel y despliegas vía CI/CD.
5) Síntoma: La actualización inicia, luego se queda; la carga del servidor sube; I/O wait aumenta
- Causa raíz: Almacenamiento lento o latencia en filesystem de red durante operaciones de unzip/rename.
- Solución: Mueve el código al disco local, mantén almacenamiento compartido solo para uploads, o rediseña las actualizaciones para que sean basadas en artefactos. Investiga cuellos I/O y uso de inodos.
6) Síntoma: El mensaje de mantenimiento vuelve a aparecer justo después de eliminarlo
- Causa raíz: Otro proceso de actualización está fallando repetidamente y recreando
.maintenance, a menudo vía auto-updates o cron. - Solución: Desactiva actualizaciones automáticas temporalmente, inspecciona cron jobs y localiza el componente que falla mediante logs y salida WP-CLI de actualizaciones.
7) Síntoma: Solo /wp-admin muestra problemas; el front-end parece bien
- Causa raíz: Endpoint de actualización del admin fallando; puede ser por timeouts de PHP, reglas WAF bloqueando POST o plugin roto cargado solo en admin.
- Solución: Revisa logs de WAF, timeouts de PHP y errores de plugins específicos del admin. Actualiza usando WP-CLI para evitar timeouts del navegador.
Listas de verificación / plan paso a paso
Lista de restauración de emergencia (recupera a los usuarios)
- Verifica la capa: ¿La respuesta de mantenimiento viene del origen o está cacheada más arriba?
- Revisa
.maintenance: Si está presente y obsoleto, elimínalo. - Vuelve a probar: Confirma HTTP 200 y que la página de inicio se renderice.
- Revisa logs: Busca fatales de PHP y errores de permisos durante la ventana de la actualización.
- Arregla componente roto: Reinstala/restaura el plugin/tema/core según sea necesario.
- Estabiliza el almacenamiento: Asegura que el espacio en disco y los inodos no estén casi a cero.
- Purga cachés: Caché de objetos + caché de página + caché CDN según corresponda.
- Valida rutas críticas: Login, panel admin y cualquier flujo de ingresos.
Plan de recuperación controlada (cuando sospechas actualizaciones parciales)
- Pon el sitio en mantenimiento intencional (opcional): Si tienes un plugin/página de mantenimiento real, úsalo en lugar de depender del caos de
.maintenance. - Identifica la actualización exacta que falló: Usa listas de WP-CLI y marcas de tiempo de logs.
- Rollback o reinstalación limpia: Reemplaza directorios enteros de plugin/tema; no intentes parchear archivos faltantes manualmente.
- Verifica checksums del core: Confirma la integridad base antes de culpar a otra cosa.
- Reejecuta actualizaciones una a una: Vigila logs durante cada actualización.
- Documenta la causa raíz: Disco, inodos, permisos, caché o modelo de proceso—elige una causa primaria y arréglala.
Lista de modelo operativo (elige tu estrategia)
Aquí es donde los equipos dejan de pisarse los talones. Decide cómo ocurren las actualizaciones en tu entorno:
- Modelo A: WordPress se actualiza solo en el servidor. Entonces debes asegurar propiedad/ACLs correctas, espacio/inodos suficientes y reglas de caché seguras.
- Modelo B: Despliegues inmutables (recomendado para producción seria). Entonces desactiva actualizaciones desde el panel, construye artefactos en CI y despliega de forma atómica con rollback.
El Modelo A puede funcionar. El Modelo B escala mejor. Mezclarlos produce el tipo de incidente donde todos tienen razón y el sitio sigue caído.
Prevención: deja de revivir este incidente
Deja de hacer “Actualizar todo” en producción
Actualiza un componente a la vez. Vigila el sistema. Si falla, sabrás qué falló.
“Actualizar todo” es eficiente para humanos y brutal para la depuración.
Dale a las actualizaciones los recursos que necesitan
Las actualizaciones no consumen mucha CPU, pero sí sistema de archivos. Eso significa:
- Mantén espacio libre real en disco (no “99% usado pero técnicamente bien”).
- Vigila inodos, especialmente en rootfilesystems pequeños y capas overlay de contenedores.
- Evita ejecutar código de plugin/tema en filesystems de red lentos si puedes.
Haz que la caché respete la realidad
Si tu edge cachea 503s por largos periodos, estás eligiendo “apagones más rápidos”. A veces es defendible. A menudo es puro cargo cult.
Asegura que tu CDN/proxy trate respuestas de mantenimiento como no cacheables a menos que quieras ese comportamiento intencionalmente.
Registra y observa actualizaciones como si importara
WordPress es software de aplicación. Las actualizaciones son despliegues. Trátalas como tal:
- Captura errores de PHP de forma centralizada.
- Registra la hora de las actualizaciones (incluso un simple changelog ayuda).
- Alerta sobre tasas sostenidas de 503 y picos de errores durante la ventana de actualización.
Usa WP-CLI para actualizaciones, especialmente en sitios con mucho tráfico
Las actualizaciones desde el navegador son frágiles: dependen de que una sola petición HTTP sobreviva el tiempo suficiente. Las actualizaciones con WP-CLI son más controlables, más fáciles de registrar y de ejecutar en una sesión que no muere cuando tu laptop cambia de Wi‑Fi.
Una cita para mantenerte honesto
“La esperanza no es una estrategia.” — General Gordon R. Sullivan
No tienes que convertirte en filósofo por esto. Simplemente deja de depender de “usualmente se limpia sola” como plan operativo.
Preguntas frecuentes
1) ¿Es seguro eliminar el archivo .maintenance?
Por lo general, sí—si la actualización no está corriendo activamente. Eliminándolo quitas el bloqueo. El riesgo es que expones a los usuarios a un sitio parcialmente actualizado. Si sospechas actualizaciones parciales, elimina el bloqueo y luego verifica inmediatamente los logs y reinstala el componente roto.
2) ¿Dónde está exactamente .maintenance?
En el directorio raíz de WordPress—típicamente el mismo directorio que contiene wp-config.php, wp-admin y wp-includes. No está dentro de wp-content.
3) ¿Por qué WordPress devuelve un 503 durante el mantenimiento?
Porque es la señal correcta a clientes y caches: “servicio temporalmente no disponible”. El problema es cuando las cachés lo manejan mal, o cuando “temporalmente” se convierte en “hasta que llegue un humano”.
4) El archivo desapareció, pero todavía veo el mensaje de mantenimiento. ¿Y ahora?
Sospecha primero de la caché. Prueba el origen directamente y purga CDN/proxy de reverso/caché de página. Si el origen es 200 pero el edge sigue sirviendo 503, ya no es WordPress—es estado de caché.
5) ¿Puede un plugin activar el modo mantenimiento sin que yo lo actualice?
Sí. Las actualizaciones automáticas, actualizaciones de traducciones y algunos mecanismos de actualización de hosts gestionados pueden activar mantenimiento. Además, un plugin puede romper el proceso de actualización, dejando el bloqueo atrás aun si el disparador fue otra cosa.
6) ¿Debería desactivar las actualizaciones automáticas para prevenir esto?
No desactives las actualizaciones de seguridad solo porque las actualizaciones alguna vez te hicieron daño. En su lugar, arregla las causas subyacentes: permisos, disco/inodos y un proceso de actualización seguro (WP-CLI, staging, artefactos).
Desactivar auto-updates cambia un incidente de fiabilidad por uno de seguridad. No es una buena negociación.
7) ¿Por qué ocurre más en hosting compartido?
El hosting compartido suele tener disco restringido, I/O limitada, permisos extraños y timeouts de PHP. El mecanismo de actualización de WordPress asume que puede escribir y renombrar archivos rápido. En hosting compartido, esa suposición suele ser falsa.
8) ¿Cómo prevengo actualizaciones parciales de plugins?
Usa un modelo de despliegue consistente. Prefiere despliegues basados en artefactos o al menos actualizaciones con WP-CLI ejecutadas en una sesión estable. Asegura espacio/inodos adecuados y propiedad/ACLs correctas. Evita actualizar en horas pico donde los timeouts son más probables.
9) ¿Ejecutar WordPress en NFS/EFS empeora esto?
Puede. Las actualizaciones implican muchas operaciones con archivos pequeños (pesadas en metadatos). Los filesystems de red pueden introducir picos de latencia que causan timeouts y movimientos parciales. Si debes usar almacenamiento compartido, mantén las uploads allí y despliega el código localmente.
10) ¿Cuál es la solución “enterprise” más limpia?
Desactiva actualizaciones desde el panel en producción, construye artefactos versionados en CI, despliega de forma atómica y guarda una ruta de rollback. Deja que WordPress sea una aplicación, no un editor interactivo de archivos.
Conclusión: próximos pasos que realmente ayudan
Si estás atascado en “Brevemente no disponible por mantenimiento programado”, tu victoria más rápida casi siempre es:
confirmar origen vs caché, eliminar .maintenance si está obsoleto y luego validar qué rompió la actualización.
Después de eso, arregla la causa real: permisos, disco/inodos, almacenamiento lento o un proceso de actualización que depende de una petición de navegador frágil.
Pasos prácticos siguientes:
- Pon “revisar
.maintenance+ revisar disco/inodos + revisar logs” en tu runbook de guardia. - Elige un modelo de actualización (auto-actualización o despliegue inmutable) y aplícalo.
- Haz que las respuestas 503 no sean cacheables salvo que realmente quieras outages cacheados.
- Usa WP-CLI para actualizaciones controladas y registradas—un componente a la vez.