Saltar al contenido principal

Cómo hacer OTA Updates en apps de CapacitorJS correctamente

Aprende a hacer OTA updates en apps de CapacitorJS y Electron con Capgo, cubriendo setup, signing, canales, CI/CD, testing y rollback en una guía práctica.

Cómo hacer OTA Updates en apps de CapacitorJS correctamente

Encuentras un error en el checkout un viernes por la tarde. El fix ya está en tu capa web de Capacitor, pero la revisión de la App Store tardará tres días. Los usuarios de Android pueden recibir un nuevo paquete antes, pero obligar a cada cliente a reinstalar un Native Build para un cambio de JavaScript es un desperdicio.

Esa es la razón práctica por la que los equipos aprenden a hacer OTA updates en apps de CapacitorJS. Un release over-the-air controlado puede entregar un web bundle firmado a los binarios instalados, descargarlo en segundo plano y aplicarlo al siguiente inicio, mientras los cambios nativos siguen el proceso de la tienda. Lo difícil no es subir un archivo. Es mantener el version targeting, signing, control de rollout, observabilidad y recuperación alineados en toda una flota.

Table of Contents

Por qué las OTA son clave para equipos de CapacitorJS

Una app Capacitor suele tener dos superficies de lanzamiento. El binario nativo contiene el shell de la plataforma, permisos, plugins, iconos, entitlements y otras capacidades revisadas por la tienda. La capa web contiene JavaScript, CSS, HTML, routing, copy y assets. Las actualizaciones OTA se encargan de la segunda superficie, permitiendo que un equipo corrija un flujo de checkout roto sin reconstruir el shell nativo, siempre que el cambio se mantenga dentro de los límites de la plataforma y las políticas de la tienda descritas en la guía de OTA de Capgo.

Diagrama que ilustra la importancia de las actualizaciones OTA comparando los retrasos de las tiendas con las correcciones instantáneas.

El beneficio operativo es más que velocidad. Los binarios instalados no se actualizan al unísono. Algunos clientes usan un Native Build antiguo, otros una versión reciente de la tienda, y cada binario puede tener distintas APIs nativas disponibles para el web bundle. Un bundle compilado para un API nativo no compatible puede fallar aunque el diff de JavaScript sea válido. Eso convierte a la OTA en un sistema de compatibilidad, no en un atajo para evitar el release engineering.

Trata al updater como un delivery pipeline

Un setup de producción requiere una secuencia clara:

  1. Instala el bridge nativo: Añade el paquete del updater y sincroniza Capacitor para que iOS y Android lo reconozcan.
  2. Firma el bundle: Mantén el material de firma fuera del repositorio e integra la verificación en el flujo del cliente.
  3. Define un channel: Enruta deliberadamente cohortes de staging, beta, producción o específicas de clientes.
  4. Automatiza la entrega: Deja que el CI haga el build, sign, upload y promote solo tras pasar los tests.
  5. Observa la adopción: Rastrea señales de descarga, instalación, arranque, crashes y salud por canal y binario.
  6. Haz rollback rápido: Restaura un bundle conocido desde el servidor y mantén la protección de recuperación en el cliente.

Capgo es una opción para este workflow. Su updater Capacitor open source y su servicio cloud publican bundles web firmados en canales específicos, los aplican en el siguiente arranque y exponen información de entrega por versión y dispositivo. Los equipos que evalúen disponibilidad y resiliencia de releases también pueden revisar la disponibilidad de apps para aplicaciones Capacitor.

Regla práctica: Si no puedes identificar a qué binario nativo apunta un bundle, no lo promuevas a producción.

El OTA tiene éxito cuando reduce releases innecesarios en la store sin ocultar el límite entre el code web y el code nativo. La pregunta no es si tu equipo puede hacer push de un bundle. Es si puedes explicar quién lo recibió, por qué era elegible, qué pasó tras el arranque y cómo restaurarás el servicio si el bundle falla.

Requisitos previos e instalación del updater de Capgo

Antes de abrir la terminal, confirma que el proyecto y las cuentas de release estén listas. Necesitarás una aplicación Capacitor 5 o 6 con @capacitor/cli inicializada, Node 18 o superior, cuentas activas de Apple Developer y Google Play Console para los binarios, y una cuenta de Capgo cloud con un appId y una clave API.

La primera instalación es intencionalmente pequeña:

npm install @capgo/capacitor-updater
npx cap sync
npx @capgo/cli init

npm install añade el paquete de JavaScript y la dependencia nativa. npx cap sync es el paso que la gente suele saltarse, y esa omisión deja el bridge nativo sin enlazar. La capa de JavaScript puede compilar, pero el runtime llamará después a un bridge que no está presente en el binario instalado. Ejecuta la sincronización tras instalar y de nuevo cuando cambie la configuración de un plugin nativo.

El inicializador parchea tu capacitor.config.ts con la configuración del updater, el endpoint web y el canal por defecto. No aceptes el parche a ciegas. Abre el archivo y verifica explícitamente la identidad de la app y el contrato de actualización:

const config: CapacitorConfig = {
  appId: 'com.example.app',
  appName: 'Example',
  version: '1.0.0',
  autoUpdate: true,
  updateUrl: '',
  capgo: {
    channel: 'staging'
  }
}

La estructura exacta generada puede variar según tu proyecto y la versión de CLI, pero los valores importantes son los mismos. appId debe coincidir con el binario instalado, version debe describir la relación con el Native Build, autoUpdate debe reflejar tu política de lanzamiento, updateUrl debe apuntar al servicio en el que confía tu binario, y el capgo bloque debe identificar el canal inicial.

Verifica antes de generar un release

Ejecuta el comando de diagnóstico antes de abrir Xcode o Android Studio:

npx @capgo/cli doctor

Un resultado limpio debe confirmar que CLI está disponible, la configuración del proyecto es legible, se detecta el paquete del updater, existen los identificadores de la app y la autenticación llega a la cuenta configurada. No debe reportar falta de sync nativa, identidad de app ausente o configuración de updater inválida.

Captura de pantalla de https://capgo.app/docs/img/cli-doctor.png

Mantén el primer Native Build deliberadamente simple. Instálalo en un dispositivo iOS y Android físico, ejecútalo con acceso a red, ciérralo y vuelve a abrirlo, y confirma que el updater puede chequear sin afectar el flujo de inicio normal. El workflow de instalación del updater de Capacitor es útil cuando necesitas comparar la configuración del proyecto con el setup esperado de los plugins.

Cómo lanzar tu primer bundle OTA de forma segura

Trata el primer bundle como una prueba de ruta de release, no como un lanzamiento de feature. Crea o rota la signing key antes de preparar el artifact:

npx @capgo/cli key create

Guarda la clave privada en un gestor de secretos. No la subas al repositorio, no la guardes en archivos del proyecto ni la expongas en los logs de CI. El path de confianza nativo requiere el material de verificación público. Solo el job de firmado debe tener acceso a la clave privada.

Cambia la versión del lado de JavaScript en package.json o en los metadatos de tu web release. Mantén los campos de la versión nativa sin cambios si es un fix solo web. Un bundle OTA no puede añadir code nativo ni alterar las capacidades declaradas por el binario instalado; un cambio en la versión nativa ocultaría la compatibilidad en lugar de mejorarla.

Sube el artefacto firmado al canal correspondiente:

npx @capgo/cli bundle upload --channel production

Un upload exitoso solo confirma que el servidor aceptó la petición. Revisa el output del comando y verifica el bundle identifier, el constraint de la native-version, el checksum firmado y el canal asignado. Esos campos identifican el artefacto y muestran si los binarios instalados son aptos para recibirlo.

Usa el dashboard como un release gate

La vista de detalle del bundle debe resolver cuatro dudas sobre el release:

  • Versión nativa mínima: ¿Qué binario más antiguo puede ejecutar este bundle?
  • Versión nativa máxima: ¿Qué binarios más nuevos se han excluido intencionadamente?
  • Canal: ¿Qué audiencia puede descubrir el artifact?
  • Porcentaje de rollout: ¿Qué parte de esa audiencia elegible puede recibirlo?

Iniciar exposición en producción a las 5%, luego define la evidencia necesaria para la expansión. Verifica el éxito de la descarga e instalación, los cold starts normales, las sesiones sin crashes y los errores de JavaScript en el flujo modificado. Mantén la identidad del artifact y los controles de entrega visibles en el dashboard de Capgo.

Screenshot de https://capgo.app/docs/img/bundle-detail.png

Usa un debug build para probar la ruta del dispositivo. getCurrent() reporta el bundle activo, y notifyAppReady() confirma que el nuevo bundle alcanzó un estado saludable:

import { CapacitorUpdater } from '@capgo/capacitor-updater'

const current = await CapacitorUpdater.getCurrent()
console.log(current)

await CapacitorUpdater.notifyAppReady()

Llama a readiness solo después de que la app se haya inicializado lo suficiente para pasar tus health checks. Si nunca confirma el readiness, la recuperación automática podría marcar el bundle como fallido en el siguiente cold start. Esa salvaguarda protege a los usuarios de producción, pero también puede hacer que un test incompleto parezca un problema de entrega. Registra el bundle activo y el resultado de startup de cada dispositivo de test antes de expandir la exposición.

Channels, Rollouts y automatización CI/CD

Los Channels son la capa de enrutamiento entre un bundle publicado y un dispositivo instalado. También son tu gate de release. Un channel de staging debe apuntar a un native binary conocido, un channel beta debe servir a un cohort controlado, y production solo debe avanzar tras pasar los smoke tests del channel anterior.

Crea una ruta de staging con nombres explícitos:

npx @capgo/cli channel create staging
npx @capgo/cli bundle assign <bundle-id> --channel staging

Vincula ese canal a la versión nativa que usan tus dispositivos de prueba. Los testers deben ejecutar el mismo binario que soportará producción, no un build de desarrollo local con plugins extra o una configuración distinta. Una vez que pase el smoke suite, promociona el artefacto probado en lugar de subir un segundo bundle ligeramente diferente.

Tu mapa de canales debe residir en capgo.config.json y revisarse como el code de la aplicación. Mantén nombres de canales estables, identifica el rango de compatibilidad nativa previsto y haz que la promoción a producción sea una acción de CI explícita. Para equipos que gestionan la exposición de features junto con la entrega, estos consejos de gobernanza de feature flags ofrece una forma útil de separar los permisos de despliegue de la activación para el usuario.

Conecta la promoción con tu CI

Un diseño práctico de GitHub Actions tiene dos rutas:

  • Pull requests: Construye la capa web, fírmala con una credencial de preview restringida y publícala en un canal de preview efímero. Destruye o deja expirar ese canal cuando se cierre el pull request.
  • Releases de main con tags: Ejecuta unit tests, construye el bundle de producción, valida su restricción de versión nativa, súbelo y promociónalo solo cuando el job de test termine con éxito.

Un comando de promoción puede verse así:

npx @capgo/cli bundle promote <bundle-id> \
  --to-channel production \
  --percent 5

Aumenta la exposición en pasos deliberados como 25%, 50% y 100%, con una aprobación de CI o un job monitoreado entre cada paso. Los porcentajes y comandos son controles, no pruebas de seguridad. Un build exitoso te dice que el bundle es sintácticamente válido. No te dice cómo se comporta en un binario nativo específico, con estado local persistido, una conexión lenta o un dispositivo que reanuda una sesión antigua.

Límite de release: Un web bundle pertenece a una ventana de compatibilidad de binario. Un channel nunca debe convertirse en un vacío legal para servir code que haga referencia a APIs nativas que la app instalada no contiene.

Mantén la coherencia en TestFlight y los builds de Android internal-track vinculando cada bundle a la versión nativa exacta para la que fue construido. Si el Native Build cambia, publica un nuevo bundle orientado a esa compatibilidad o crea un nuevo mapping de channel. La guía de integración de Capgo GitHub Actions puede ayudarte a traducir esa política en pasos de workflow repetibles.

Un diagrama que ilustra los tres pasos de los software channels y la automatización: Staging Channel, Pin Binary y CI/CD Auto-Deploy.

Estrategias de testing y rollback automático

Un release OTA puede pasar el CI y aun así fallar tras la activación. El fallo puede depender del bundle, el binario nativo, el estado guardado del dispositivo o las condiciones de red. Un simulador puede confirmar que una pantalla se renderiza, pero no puede cubrir cada binario instalado ni mostrar si un fallo en el startup se recupera correctamente.

Usa tres niveles de prueba:

  1. Tests de bundle en CI: Ejecuta unit tests, type checks, linting y un build web de producción. Prueba los flujos de checkout, autenticación, navegación y persistencia en lugar de limitarte a la compilación.
  2. Canal de dispositivos privados: Prepara un canal privado con dispositivos físicos que ejecuten el binario nativo anterior. Cubre ambas plataformas, instalaciones limpias, actualizaciones y estados de almacenamiento representativos.
  3. Canary de producción: Empieza con un grupo pequeño, crash reporting conectado y alertas de errores de JavaScript. Trata los fallos de inicio como urgentes, ya que los usuarios afectados podrían no llegar al code que reporta el error.

El Guía de testing OTA de Capacitor explica la mecánica de testing. La regla operativa es simple: prueba cada update contra el binario nativo que debe proteger.

Separa el control del servidor de la recuperación del cliente

El rollback en el servidor detiene las nuevas descargas:

npx @capgo/cli channel set production --bundle <previous-id>

Esto cambia lo que los dispositivos elegibles descubrirán a continuación. No borra un bundle ya descargado o activo en cada dispositivo, por lo que el cliente también necesita controles de recuperación. Configura el updater para mantener un fallback estable y revertir tras una condición de fallo de inicio definida.

Una ruta de recuperación fiable incluye:

  • Seguimiento de fallos de descarga: Distinguir problemas de conectividad de artefactos inválidos.
  • Seguimiento de fallos de instalación: Detectar problemas de desempaquetado, verificación y del filesystem.
  • Seguimiento de salud del arranque: Confirmar que la app alcanza un estado utilizable tras la activación.
  • Fallback automático: Restaurar el bundle estable anterior cuando el inicio falla repetidamente.
  • Escalación manual: Preservar los identificadores del dispositivo y del bundle para soporte e ingeniería.

A escala de flotas, una tasa de error pequeña sigue generando una carga de soporte significativa. Una tasa de éxito del 99.95% en actualizaciones OTA todavía implica unos 1,000 fallos por cada millón de dispositivos, according to benchmarks de pruebas OTA para flotas de IoT. La misma fuente describe guardrails como rollback en menos de 30 minutos, tasa de crash inferior al 0.1% y un 98% de dispositivos dentro del margen soportado. Tómalos como ejemplos de referencia, no como criterios de aceptación universales. Define el error budget según el riesgo de la app y el impacto en el usuario.

Firma, seguridad y lo que OTA no puede cambiar

Una actualización sin firmar convierte al endpoint de entrega en parte de tu superficie de ataque de la cadena de suministro. TLS protege la conexión, pero el cliente también debe confirmar que el artefacto descargado proviene de un proceso de release autorizado y no fue reemplazado o alterado en tránsito.

Genera un keypair Ed25519 con las herramientas de actualización. Guarda la clave privada en un secreto de CI e incrusta la clave pública de verificación en el binario nativo durante el build de la app. El cliente debe verificar cada bundle antes de la activación. Limita los tokens de CLI por entorno y alcance de permisos, conserva los logs de upload y promoción, y exige una autenticación fuerte para acciones en producción.

Trata la rotación de llaves como una migración de compatibilidad, no como un simple cambio de configuración. Genera una llave de reemplazo, lanza un Native Build que confíe tanto en la llave pública actual como en la nueva, y luego firma los releases con la nueva llave privada. Elimina la llave antigua solo cuando los binarios nativos compatibles ya hayan adoptado la nueva. Eliminar la confianza demasiado pronto impedirá que los binarios antiguos acepten actualizaciones válidas. Mantener una llave comprometida de forma indefinida anula el propósito de la rotación.

Define el límite en el plan de release

OTA gestiona cambios en la capa web. Se requieren releases nativos cuando un cambio depende de capacidades ausentes en el binario instalado:

Categoría Enviar vía OTA Requiere release nativo
Comportamiento de la aplicación Lógica de JavaScript, routing, validación y manejo de estado Implementación de plugins nativos
Presentación CSS, HTML, copy, theme tokens y assets de imagen compatibles Icono de la app y recursos de splash
Acceso a la plataforma Llamadas existentes de Capacitor a capacidades ya presentes en el binario Nuevos permisos, entitlements o APIs nativas
Configuración Configuración web compatible y reglas de contenido remoto Info.plist, AndroidManifest.xml, identidad de firma
Metadatos de la tienda Ninguno que cambie el comportamiento revisado por la tienda o metadatos de versión Metadatos sensibles a políticas de tiendas y cambios en el número de versión

El Documentación de firma de Capacitor updater code explica el modelo de verificación. Aplícalo operativamente con logs de auditoría contra manipulaciones, verificación de certificados, TLS, controles de acceso estrictos y un proceso de investigación ante spoofing de versiones o compromiso de llaves.

La compatibilidad sigue siendo clave porque la base de usuarios con nativo instalado cambia gradualmente. Apple reportó un 66% de todos los dispositivos activos en iOS 26 y un 74% de los dispositivos lanzados en los últimos cuatro años en iOS 26, mientras que otro informe situó a iOS 26 en un 79% de todos los dispositivos al final del ciclo, según se resume en la mobile OTA key-management research. Estas cifras cubren distintos momentos y poblaciones de dispositivos. La conclusión práctica es la misma: incluso las plataformas maduras no actualizan todos los dispositivos a la vez. Asigna bundles por versión nativa y capacidad, en lugar de asumir que un único artefacto OTA sirve para toda la flota.

Checklist operativo antes de cada release

Mantén el checklist de release en una sola página, guardada en el repositorio o runbook. Actualízalo tras cada incidente. Un control añadido tras un fallo real suele prevenir su recurrencia.

Antes del upload

  • Confirma la compatibilidad: Verifica que el bundle apunte al binario nativo exacto y no use APIs de plugins no disponibles.
  • Revisa el artefacto: Haz el build desde un workspace limpio, inspecciona los archivos generados y confirma la versión web deseada.
  • Protege el signing: Confirma que el CI tenga el secret y la key esperados. Verifica que los logs no expongan información privada.
  • Valida los channels: Revisa los mappings de staging, beta y production antes de asignar el bundle.
  • Preserva la recuperación: Registra el último bundle estable conocido y verifica que el fallback siga funcionando.
  • Realiza smoke tests físicos: Prueba el arranque, login, checkout, navegación, persistencia y la preparación para el update en dispositivos reales.

Durante la promoción

Lanza primero a un grupo limitado y vigila las métricas de impacto:

  • Sesiones sin crashes: Compara el resultado con el bundle anterior e investiga regresiones.
  • Tasa de errores de JavaScript: Agrupa errores por bundle, versión nativa, plataforma y ruta de la feature.
  • Comportamiento en cold-start: Verifica si la activación afecta el arranque o deja la pantalla en blanco.
  • Cobertura de features: Confirma que la funcionalidad remota coincida con el binario que la recibe.
  • Adopción y fallos: Separa los dispositivos aptos que no han buscado updates de los que fallaron.

Mantén la primera ventana de observación post-promoción durante 30 minutos antes de ampliar la exposición. Si se rompe una ruta crítica, revierte el canal de producción al bundle anterior, conserva los logs y decide si el fix va en otro bundle OTA o en un nuevo release nativo.

Disciplina el día del despliegue: Un bundle de fallback solo ayuda si el equipo conoce su identificador, rango de compatibilidad y el comando de restauración.

Considera esta checklist como un code operativo compartido. Capgo puede ofrecer entrega de bundles firmados, segmentación de canales, controles de rollout, historial de actualizaciones y observabilidad a nivel de dispositivo. Tu equipo sigue siendo responsable de la política de compatibilidad y de la decisión de promover.


Capgo ofrece a los equipos de CapacitorJS una vía controlada para updates firmados de JavaScript, CSS, configuración y assets, con canales, entrega escalonada, protección contra rollback y observabilidad de releases. Aplica esta checklist en tu próximo despliegue, pruébala con un binario de staging y evalúa Capgo para el workflow de producción.

Live Updates para apps de Capacitor

Si hay un bug en la capa web, publica el fix con Capgo en lugar de esperar días a la aprobación de la app store. Los usuarios reciben la actualización en segundo plano mientras los cambios nativos siguen el proceso de revisión normal.

Lo último de nuestro blog

Capgo te da los mejores insights para crear una app móvil realmente profesional.