Cuando los SDK opcionales actúan como infraestructura core

Un fallo de lanzamiento muy común en apps móviles hechas con vibe coding es que analytics, attribution o crash reporting se inicializan junto con los servicios realmente críticos. Si uno de esos SDK opcionales se comporta mal en un dispositivo concreto o bajo cierta condición de red, toda la app puede morir antes de que aparezca la primera pantalla.

Esto pasa porque el código de setup generado por IA tiende a tratar todas las dependencias como igual de importantes. Sin un sistema de niveles explícito, no existe distinción arquitectónica entre infraestructura imprescindible y observadores nice-to-have. Todo termina convertido en imprescindible por accidente.

Tres niveles de dependencias

Cada dependencia de tu app cae en uno de tres buckets. Trazar estas líneas de forma explícita es la diferencia entre una app que sobrevive al crecimiento y otra que muere por mil crashes en producción:

  • Hard dependencies: si fallan, tu app no puede renderizar. Parseo de config. Creación de storage. Construcción de servicios core. Son tus cimientos.
  • Soft dependencies: pueden fallar con degradación elegante. Auth. Features dependientes de la red. Flujos dependientes de permisos. El app shell sigue renderizando; el usuario ve una experiencia degradada, no un crash.
  • Optional dependencies: pueden fallar en silencio. Analytics. Crash reporting. A/B testing. Nunca bloquean la app. Son observadores, no participantes.

El error que cometen la mayoría de las apps hechas con vibe coding es tratar todo como hard. Cada SDK se inicializa en el startup. Cada fallo se convierte en un crash de arranque. Pero tu SDK de analytics no merece el mismo estatus que tu capa de storage.

La frontera de hard dependencies

La frontera hard valida la config y construye los servicios. Si falla, la app muestra una pantalla de error con un botón de reintento, no un vacío blanco que los usuarios castigarán con una estrella en la App Store.

// src/context/hard-dependency-boundary.tsx
// This is the gatekeeper. If it fails, nothing else renders.

import * as SplashScreen from 'expo-splash-screen'

void SplashScreen.preventAutoHideAsync()

export function HardDependencyBoundary({
  children,
}: {
  children: (services: Services) => ReactNode
}) {
  const { services, ready, error, retry } =
    useHardDependencies()

  useEffect(() => {
    if (ready || error) void SplashScreen.hideAsync()
  }, [ready, error])

  if (error) {
    return (
      <ErrorScreen
        title='Startup failed'
        message={error.message}
        onRetry={retry}
      />
    )
  }

  if (!ready || !services) return null

  return <>{children(services)}</>
}

Fíjate en el patrón de render props. La frontera pasa los servicios inicializados a sus hijos. Los hijos no construyen servicios; los reciben. La construcción ocurre exactamente una vez, y cualquier fallo se captura en la frontera, no se filtra a un crash report de producción.

La frontera opcional

Ahora compáralo con las dependencias opcionales. Estas nunca deberían hacer crash a tu app. Si Mixpanel se cae, tu app ni se inmuta:

// src/context/optional-dependency-boundary.tsx
// If analytics fails, we log a warning and keep going.

export function OptionalDependencyBoundary({
  children,
}: PropsWithChildren) {
  const { analytics, crashReporting } = useServices()

  useEffect(() => {
    try {
      analytics.track('app_started')
    } catch (error) {
      if (__DEV__) console.warn('Analytics failed:', error)
    }

    try {
      crashReporting.setContext('app', { started: true })
    } catch (error) {
      if (__DEV__) console.warn('Crash reporting failed:', error)
    }
  }, [analytics, crashReporting])

  return <>{children}</>
}

La diferencia de postura es evidente. Frontera hard: si falla, muestra una pantalla de error. Frontera opcional: si falla, registra una advertencia y sigue. Ambas son explícitas. Ninguna finge ser lo que no es.

La mayoría de los crashes en producción en apps hechas con vibe coding vienen del mismo error: tratar dependencias soft u optional como si fueran hard. El Autotomy Expo Starter Pack traza estas líneas desde el día uno para que nunca aprendas esta lección a las 2 AM.