Code push en Flutter con Shorebird: qué puedes actualizar sin pasar por la store (y qué no)

Un code push te deja cambiar el código Dart de una app Flutter ya instalada sin subir una versión nueva a App Store ni a Google Play. El dispositivo descarga el parche y lo aplica la próxima vez que se abre la app. Para un bug de lógica que se te ha colado en producción, es la diferencia entre corregirlo hoy o esperar dos días de revisión. Pero el margen es estrecho: solo toca la capa Dart, deja fuera el código nativo y el motor de Flutter, y Apple y Google acotan qué puedes cambiar por esta vía. Antes de meterlo en tu flujo de release conviene saber dónde está la línea.

La herramienta de referencia para esto en Flutter es Shorebird, del equipo que arrancó el propio proyecto Flutter en Google. Este artículo no es un tutorial de instalación; es la decisión que tienes que tomar antes: qué resuelve, qué no, y cuándo lo desaconsejamos.

Qué es exactamente un parche

Shorebird sustituye el motor de Flutter por uno modificado que, al arrancar la app, comprueba si hay una versión nueva de tu código Dart. Si la hay, la descarga en segundo plano sin bloquear el inicio y la deja lista para el siguiente reinicio de la app. El usuario no ve ningún diálogo de la store ni instala nada a mano. Si necesitas que el parche entre de forma inmediata y obligatoria, puedes forzar la comprobación desde el propio código con package:shorebird_code_push.

Tres detalles operativos que cambian cómo lo usas:

  • Solo hay un parche activo a la vez por cada release. No acumulas capas; cada parche nuevo reemplaza al anterior sobre esa versión publicada.
  • El parche va atado a una release concreta. Cuando subes una versión nueva a la store, empiezas de cero: los parches no saltan de una release a otra.
  • Tienes tracks (stable, staging, beta) para validar un parche con un subconjunto antes de soltarlo a todos. Es lo que convierte el code push en algo operable y no en una ruleta.

Qué puedes actualizar y qué no

Aquí es donde mucha gente se lleva la sorpresa. Un parche modifica Dart, y solo Dart.

Lo que sí entra en un parcheLo que no
Lógica de la app y código de UICódigo nativo (Swift, Kotlin, Objective-C, Java)
Código generado (por ejemplo, localizaciones)Versión del motor de Flutter
Dependencias de pubspec.yaml sin parte nativaDependencias que incluyan código nativo
Assets como imágenes o fuentes (soporte anunciado, aún no disponible)

La consecuencia práctica: si tu hotfix toca un plugin nativo, cambia un icono de la app o exige subir de versión de Flutter, el code push no te sirve y vuelves al ciclo normal de publicación. No es una limitación menor. Buena parte de los cambios que un equipo cataloga como "urgentes" acaban tocando algo fuera de Dart, y descubrirlo el día del incidente es tarde. La regla mental sencilla: si el fix vive en tu carpeta lib/, es candidato; si baja al proyecto Android o iOS, no.

Que los assets todavía queden fuera pesa más de lo que la tabla sugiere. Un texto legal mal redactado lo arreglas por parche porque es un String en Dart; una imagen con ese mismo texto dentro, no.

Lo que permiten App Store y Google Play

El code push existe en una zona que las dos tiendas regulan con cuidado, porque roza algo que ambas prohíben: que una app se actualice a sí misma por fuera de la store.

En Apple, la guía 2.5.2 y el acuerdo de licencia (DPLA) prohíben descargar y ejecutar código que introduzca o cambie funcionalidades. La excepción es el código interpretado: Apple lo permite siempre que no altere el propósito principal de la app, no monte una tienda de código dentro de la app y no esquive las protecciones de seguridad del sistema. En la revisión de octubre de 2025 esa cláusula se reordenó dentro del contrato y pasó a llamarse "Executable Code", pero el fondo no cambió. Shorebird encaja en ese hueco porque sus parches ejecutan Dart a través de su propio intérprete y arreglan lógica que ya existía, sin añadir capacidades que habrían requerido pasar por revisión.

Conviene ser honesto con el matiz: la excepción de código interpretado se escribió pensando en JavaScript sobre WebKit, no en un intérprete de Dart. Shorebird opera en un terreno adyacente, y su seguridad viene de la disciplina de alcance, no de una bendición explícita de Apple para su motor. Mientras uses los parches para lo que son (correcciones y ajustes de lo ya revisado), estás dentro. El día que los uses para activar una pantalla que el revisor nunca vio, el problema no es 2.5.2 sino 2.3.1: funcionalidades ocultas o latentes. A principios de 2026 Apple retiró apps del tipo Replit o Vibecode justo por esto, por generar y ejecutar código que modificaba su comportamiento en tiempo de ejecución al margen de la revisión. Esa es la frontera real.

Google Play es más directo. Su política de abuso de dispositivos y red prohíbe que una app se modifique o actualice fuera de Play, con una excepción para el código que corre en una máquina virtual o un intérprete, siempre que no habilite violaciones de las políticas de Play. Shorebird cae dentro de esa excepción por la misma razón: parchea Dart interpretado, no binarios nativos.

Resumen para tu equipo legal y de producto: parchear bugs y ajustar comportamiento existente está permitido en ambas tiendas; usar el canal para colar features que cambian lo que la app es, no.

Cuándo lo usamos y cuándo no

Nuestra posición, después de llevar Flutter a producción desde 2017, es que el code push es una herramienta de mantenimiento excelente y un mal sustituto del release.

Lo metemos sin dudar cuando:

  • Hay un bug de lógica Dart en producción que sangra (un crash en un flujo de pago, un cálculo mal, una llamada rota a una API) y esperar la revisión tiene coste real.
  • Necesitas un kill-switch o un feature flag que apague algo rápido sin republicar.
  • Quieres probar una variante de lógica en un track de staging antes de comprometerte con ella.

Lo desaconsejamos cuando:

  • El equipo no tiene disciplina de alcance. El code push convierte "subimos una feature el viernes por la tarde" en una tentación, y ahí es donde se rompe la relación con las tiendas. Si tu proceso no distingue con claridad entre un parche de corrección y una release de producto, la herramienta amplifica el desorden.
  • El cambio toca nativo, assets o motor. No es que sea mala idea; es que no funciona, y forzarlo es perder el día.
  • Tu app ya tiene un ciclo de release ágil y sano. Si publicas cada semana con un pipeline decente, el número de incidentes que solo el code push puede resolver es pequeño, y estás añadiendo una dependencia y un coste (Shorebird cobra por instalación de parche, no por release) a cambio de poco.

Ese último punto es el que más gente pasa por alto. El code push compensa cuando el ciclo de publicación es lento o cuando un bug en producción sale caro. Si tú ya tienes un pipeline de CI/CD que publica rápido, buena parte de su valor se diluye.

Cómo encaja con el resto de tu ciclo

El code push no reemplaza tu pipeline: se sienta encima. Sigues necesitando releases normales para todo lo que un parche no puede tocar, y eso incluye las cosas que no son opcionales. Cuando subes de versión de Flutter, cambias un plugin nativo o te toca recompilar contra un SDK nuevo de iOS o apuntar a la API que exige Google Play, vas por la store, con su revisión y sus plazos. El parche es para el hueco entre release y release, no para saltártelas.

Bien encajado, el code push te da un equipo que corrige en horas lo que antes tardaba días, sin renunciar al control ni pelearte con las tiendas. Usado sin criterio, solo acumula deuda y roces con los revisores. La herramienta es la misma en ambos casos; lo que cambia es la disciplina con la que separas un parche de una release.

Si estás montando el mantenimiento de una app Flutter en producción y quieres definir esa política con criterio, es parte de lo que hacemos en mantenimiento y evolución. Y si el proyecto arranca de cero, mejor dejar el pipeline y la estrategia de hotfix pensados desde el principio que remendarlos después.