Wise Hustlers β€” Digital Product & App Development Studio Logo
Get Consultation
By Wise Hustler Adminβ€’11/11/2026β€’19 min read

React Native Super-App Architecture: Building Modular Mobile Micro-Frontends with Re.Pack and Module Federation

React Native Super-App Architecture: Building Modular Mobile Micro-Frontends with Re.Pack and Module Federation

# React Native Super App Architecture Module Federation: Building Modular Micro-Frontends with Re.Pack

Summary: Monolithic mobile codebases create release bottlenecks and team friction at enterprise scale. Adopting a React Native super app architecture with Module Federation and Re.Pack decouples core host functionality from independent mini-apps. By serving remote JavaScript bundles via global CDNs, enforcing strict native bridge boundaries, and implementing offline fallback state machines, engineering teams transition from restrictive weekly App Store release trains to instant, continuous sub-team deployments while maintaining deterministic runtime stability.

---

The Enterprise Scaling Wall: Monoliths vs. Mobile Micro-Frontends

As mobile engineering organizations scale across multiple cross-functional feature squads working within a single monolithic codebase, organizational and operational friction compounds. When squads responsible for distinct product domainsβ€”such as checkout, authentication, catalog discovery, and customer supportβ€”share a single repository, a unified Metro bundler graph, and a synchronized release cycle, deployment velocity degrades.

This monolithic pattern introduces severe friction points:

1. Release Train Contention: A bug introduced by a single feature squad blocks the scheduled binary submission to Apple TestFlight and Google Play Console, stalling value delivery for every other squad.

2. Exponential Merge Conflicts: Shared navigation routers, centralized dependency locks, and singleton configuration files generate continuous merge friction across distributed product squads.

3. Bloated Local Build Times: In large-scale monolithic codebases, Metro must traverse extensive dependency graphs comprising tens of thousands of module files, substantially prolonging developer bundle compilation and cold-start start-up times.

4. Binary Bloat: Bundling every feature statically into the initial app binary inflates download sizes past cellular download warning thresholds, depressing conversion rates during user acquisition.

Monolithic Mobile Release Friction:
Squad A (Payments)    ──┐
Squad B (Catalog)     ──┼─> [Monolith Git Repo] ─> [Metro Bundler] ─> [App Store Review (Typically 24-48 Hours)]
Squad C (Onboarding)  β”€β”€β”˜          β–²
                                   β”‚
                   Single Flaky Test Blocks Entire Release Train

(Note: While Apple published metrics indicate over 90% of submissions are reviewed within 24 to 48 hours per official App Store review data, monolithic release trains introduce multi-day internal branch freezes, cherry-picking overhead, and regression sync cycles before a binary can even be submitted).

Why React Native Dominates Over Flutter for Super-App Architectures

When evaluating mobile micro-frontend foundations, engineering leadership frequently compares Flutter against React Native. Flutter compiles directly to ahead-of-time (AOT) ARM64 machine code on iOS. Under Section 2.5.2 of the Apple App Store Review Guidelines, apps may not download, install, or execute external native binary executable machine code. Consequently, Flutter cannot natively download and execute dynamic Dart machine code chunks over a CDN on iOS without relying on third-party interpreted runtimes that introduce CPU execution overhead or risk guideline compliance issues.

In contrast, React Native executes JavaScript and bytecode within an interpreted virtual machine environment (the Hermes JavaScript VM or JavaScriptCore). Section 2.5.2 permits interpreted code executionβ€”including dynamically delivered JavaScript bundlesβ€”provided that the code does not alter the primary purpose or category of the application as approved in App Store Connect, does not circumvent sandbox protections, and strictly adheres to App Store monetization requirements (such as Apple In-App Purchase under Guideline 3.1.1).

By pairing React Native with Re.Pack v5 and Module Federation, mobile engineering organizations implement a true mobile super-app architecture: a compiled native host shell that downloads, verifies, caches, and executes independent mini-app bundles on demand.

---

System Architecture Blueprint: Host Shell, Mini-Apps, and Shared Vendors

A modular React Native super app architecture module federation system separates infrastructure concerns from product domain logic. The platform is organized into three architectural layers: the Native Host Shell, the CDN Distribution Tier, and the Dynamic Remote Mini-Apps.

flowchart TD
    subgraph ClientDevice ["Client Device Runtime"]
        subgraph HostShell ["Native Host Shell (Base Binary)"]
            HostNav["Root Navigation Controller"]
            ScriptMgr["Re.Pack ScriptManager & Fallback Engine"]
            CapGateway["Native Capability Gateway & Security Sandbox"]
            NativeMods["Core Native Modules (Hermes, Camera, Push)"]
            
            subgraph SharedSingletons ["Shared Singleton Vendors"]
                ReactCore["react @ 18.3.1"]
                RNCore["react-native @ 0.76.x"]
                DesignTokens["@enterprise/design-tokens"]
            end
        end

        subgraph LocalDisk ["Local Encrypted Filesystem"]
            BundleCache["Persistent Bundle Cache (/mini_apps)"]
            ManifestStore["ETag & Version Manifest Ledger"]
        end

        subgraph RemoteMiniApps ["Mounted Remote Mini-Apps"]
            MiniCheckout["Checkout Mini-App (Remote)"]
            MiniMarket["Marketplace Mini-App (Remote)"]
            MiniLoyalty["Loyalty Mini-App (Remote)"]
        end
    end

    subgraph CDNTier ["Global Edge Distribution Tier"]
        CloudflareCDN["Cloudflare Edge CDN / AWS CloudFront"]
        CloudStorage["S3 / Cloudflare R2 Storage Bucket"]
        RemoteManifest["manifest.json (Versions & Checksums)"]
    end

    HostNav --> ScriptMgr
    ScriptMgr -->|1. Check Cache| BundleCache
    ScriptMgr -->|2. ETag Validation| CloudflareCDN
    CloudflareCDN --> CloudStorage
    CloudStorage --> RemoteManifest
    ScriptMgr -->|3. Mount Executable Code| RemoteMiniApps
    RemoteMiniApps --> SharedSingletons
    RemoteMiniApps --> CapGateway
    CapGateway --> NativeMods

1. The Native Host Shell

The Host Shell is the compiled native binary distributed via the Apple App Store and Google Play Store. It contains:

  • The native runtime (React Native 0.76+ architecture with the New Architecture enabled: Bridgeless Mode, TurboModules, and Fabric).
  • Root navigation container (@react-navigation/native) configured with an asynchronous dynamic route registry.
  • The Re.Pack ScriptManager responsible for resolving, downloading, caching, and mounting remote JavaScript chunks.
  • The Capability Gateway that controls access to sensitive native bridge modules.

2. Shared Singleton Vendors

Module Federation prevents multiple copies of fundamental libraries from loading into the Hermes JavaScript runtime. React relies on a single shared instance to manage internal hook dispatchers; bundling duplicate copies of react or react-native inside remote mini-apps causes runtime errors (Invalid hook call warnings). The Host Shell pre-loads these dependencies eagerly as singletons and shares them with all downstream mini-apps.

3. CDN Distribution Tier

Mini-apps are built by independent continuous integration (CI) pipelines and published to object storage (such as AWS S3 or Cloudflare R2). A globally distributed Content Delivery Network (CDN) serves the versioned bundles, source maps, and signed manifest files to mobile clients.

---

Production Re.Pack v5 and Rspack Configuration

Callstack's Re.Pack v5 replaces the legacy Webpack compilation pipeline with Rspack, an open-source Rust-based web bundler. According to official performance benchmarks published by the Rspack core project, Rspack achieves up to 5x to 10x faster build and incremental compilation speeds compared to Webpack 5 across enterprise bundle sizes, while maintaining direct API compatibility with the Webpack Module Federation plugin standard.

Below is an enterprise-grade rspack.config.mjs implementation demonstrating container configuration, remote definitions, and eager singleton dependency sharing.

Host Shell Configuration (`apps/host-shell/rspack.config.mjs`)

import path from 'node:path';
import * as Repack from '@callstack/repack';
import { rspack } from '@rspack/core';

export default (env) => {
  const {
    mode = 'production',
    context = Repack.getDirname(import.meta.url),
    platform = process.env.PLATFORM,
  } = env;

  if (!platform) {
    throw new Error('Platform environment variable must be specified.');
  }

  const isDev = mode === 'development';

  return {
    mode,
    context,
    entry: './index.js',
    output: {
      clean: true,
      path: path.resolve(context, 'build', platform),
      filename: 'index.bundle',
      chunkFilename: '[name].chunk.bundle',
      publicPath: Repack.getPublicPath({ platform }),
    },
    resolve: {
      ...Repack.getResolveOptions(platform),
    },
    module: {
      rules: [
        ...Repack.DEFAULT_RULES,
      ],
    },
    plugins: [
      new Repack.RepackPlugin({
        platform,
        output: {
          bundleFilename: 'index.bundle',
        },
      }),
      new rspack.container.ModuleFederationPlugin({
        name: 'HostShell',
        shared: {
          react: {
            singleton: true,
            eager: true,
            requiredVersion: '18.3.1',
          },
          'react-native': {
            singleton: true,
            eager: true,
            requiredVersion: '0.76.1',
          },
          '@react-navigation/native': {
            singleton: true,
            eager: true,
            requiredVersion: '^6.1.9',
          },
          '@enterprise/design-tokens': {
            singleton: true,
            eager: true,
            requiredVersion: '^2.4.0',
          },
        },
      }),
    ],
  };
};

Remote Mini-App Configuration (`apps/mini-checkout/rspack.config.mjs`)

import path from 'node:path';
import * as Repack from '@callstack/repack';
import { rspack } from '@rspack/core';

export default (env) => {
  const {
    mode = 'production',
    context = Repack.getDirname(import.meta.url),
    platform = process.env.PLATFORM,
  } = env;

  return {
    mode,
    context,
    entry: './index.js',
    output: {
      clean: true,
      path: path.resolve(context, 'dist', platform),
      filename: '[name].js',
      chunkFilename: '[name].chunk.js',
      publicPath: `https://cdn.enterprise.com/mini-apps/checkout/${platform}/`,
    },
    resolve: {
      ...Repack.getResolveOptions(platform),
    },
    module: {
      rules: [...Repack.DEFAULT_RULES],
    },
    plugins: [
      new Repack.RepackPlugin({
        platform,
      }),
      new rspack.container.ModuleFederationPlugin({
        name: 'MiniCheckout',
        filename: 'MiniCheckout.container.js',
        exposes: {
          './CheckoutEntry': './src/navigation/CheckoutNavigator.tsx',
          './CheckoutSummaryWidget': './src/components/CheckoutSummaryWidget.tsx',
        },
        shared: {
          react: {
            singleton: true,
            import: false, // Prevents bundling a local copy; uses host singleton
            requiredVersion: '18.3.1',
          },
          'react-native': {
            singleton: true,
            import: false,
            requiredVersion: '0.76.1',
          },
          '@react-navigation/native': {
            singleton: true,
            import: false,
          },
          '@enterprise/design-tokens': {
            singleton: true,
            import: false,
          },
        },
      }),
    ],
  };
};

---

Dynamic Bundle Loading and Offline Fallback State Machine

Mobile devices operate under variable network conditions: high-speed cellular connections transition into subway tunnels or throttled environments. A production-grade super-app must avoid blank viewports or infinite loading spinners if a remote mini-app fails to fetch over the network.

To ensure consistent application availability, the Host Shell implements an offline fallback state machine backed by a verified local filesystem cache.

stateDiagram-v2
    [*] --> IDLE
    IDLE --> FETCH_MANIFEST: User Navigates to Mini-App
    FETCH_MANIFEST --> VERIFY_LOCAL_CACHE: Manifest Retrieved
    FETCH_MANIFEST --> READ_DISK_FALLBACK: Network Error / Timeout (3000ms)
    
    VERIFY_LOCAL_CACHE --> ACTIVE_RUNTIME: Local Checksum Matches Remote
    VERIFY_LOCAL_CACHE --> DOWNLOAD_BUNDLE: Hash Mismatch / New Version
    
    DOWNLOAD_BUNDLE --> VALIDATE_INTEGRITY: Stream Complete
    DOWNLOAD_BUNDLE --> READ_DISK_FALLBACK: Download Interrupted
    
    VALIDATE_INTEGRITY --> WRITE_DISK_CACHE: SHA-256 Validated
    VALIDATE_INTEGRITY --> ROLLBACK_SAFE_BASELINE: Checksum Corrupted
    
    WRITE_DISK_CACHE --> ACTIVE_RUNTIME: Bundle Mounted into Hermes
    READ_DISK_FALLBACK --> ACTIVE_RUNTIME: Cached Bundle Available
    READ_DISK_FALLBACK --> SAFE_OFFLINE_BANNER: No Cached Version on Disk
    
    ROLLBACK_SAFE_BASELINE --> ACTIVE_RUNTIME: Mount Bundled Fallback
    SAFE_OFFLINE_BANNER --> [*]
    ACTIVE_RUNTIME --> [*]

Implementing the Resilient Script Resolver

The client-side dynamic bundle loader orchestrates local filesystem storage, remote ETag headers, and fallback execution.

import { ScriptManager, Script } from '@callstack/repack/client';
import RNFS from 'react-native-fs';

interface RemoteManifest {
  version: string;
  bundleHash: string;
  bundleUrl: string;
}

const STORAGE_ROOT = `${RNFS.DocumentDirectoryPath}/mini_app_cache`;
const NETWORK_TIMEOUT_MS = 3500;

ScriptManager.shared.addResolver(async (scriptId, caller) => {
  const platform = Script.getPlatform();
  const manifestUrl = `https://cdn.enterprise.com/mini-apps/${scriptId}/${platform}/manifest.json`;
  const localAppDir = `${STORAGE_ROOT}/${scriptId}`;
  const localManifestFile = `${localAppDir}/manifest.json`;

  await RNFS.mkdir(localAppDir);

  const fetchWithTimeout = (url: string, timeout: number): Promise<Response> => {
    return Promise.race([
      fetch(url, { headers: { 'Cache-Control': 'no-cache' } }),
      new Promise<Response>((_, reject) =>
        setTimeout(() => reject(new Error(`Network timeout for ${url}`)), timeout)
      ),
    ]);
  };

  try {
    const res = await fetchWithTimeout(manifestUrl, NETWORK_TIMEOUT_MS);
    if (!res.ok) throw new Error(`HTTP Error ${res.status}`);

    const remoteManifest: RemoteManifest = await res.json();
    const cachedBundlePath = `${localAppDir}/${remoteManifest.bundleHash}.bundle`;

    const cacheExists = await RNFS.exists(cachedBundlePath);
    if (cacheExists) {
      return {
        url: `file://${cachedBundlePath}`,
        cache: false,
      };
    }

    // Download fresh bundle to disk
    const downloadDest = `${localAppDir}/${remoteManifest.bundleHash}.tmp`;
    const downloadResult = await RNFS.downloadFile({
      fromUrl: remoteManifest.bundleUrl,
      toFile: downloadDest,
      headers: { Accept: 'application/octet-stream' },
    }).promise;

    if (downloadResult.statusCode === 200) {
      await RNFS.moveFile(downloadDest, cachedBundlePath);
      await RNFS.writeFile(localManifestFile, JSON.stringify(remoteManifest), 'utf8');

      return {
        url: `file://${cachedBundlePath}`,
        cache: false,
      };
    }
    throw new Error('Download failed');
  } catch (err) {
    // OFFLINE FALLBACK: Load most recent verified bundle from filesystem
    const manifestExists = await RNFS.exists(localManifestFile);
    if (manifestExists) {
      const savedManifestRaw = await RNFS.readFile(localManifestFile, 'utf8');
      const savedManifest: RemoteManifest = JSON.parse(savedManifestRaw);
      const fallbackPath = `${localAppDir}/${savedManifest.bundleHash}.bundle`;

      if (await RNFS.exists(fallbackPath)) {
        return {
          url: `file://${fallbackPath}`,
          cache: false,
        };
      }
    }

    // Critical Fallback: Use baked-in baseline bundle in app assets
    return {
      url: `asset:///fallbacks/${scriptId}.${platform}.bundle`,
      cache: false,
    };
  }
});

---

Native Bridge Boundary Isolation: Sandboxing Mini-Apps

In React Native, federated JavaScript modules execute within a shared JavaScript runtime environment. Without architectural boundaries, any remote mini-app could invoke native modules directly:

// Security Risk: Direct native module access without scope boundary
import { NativeModules } from 'react-native';
NativeModules.SecureKeyStore.getItem('root_enterprise_auth_token');

To prevent cross-module credential exposure, memory conflicts, and unauthorized hardware access, the host architecture establishes a Capability Gateway. Remote mini-apps do not import NativeModules directly. Instead, they interact with an injected, scoped security context.

+--------------------------------------------------------------+
|                    Remote Mini-App Domain                    |
+--------------------------------------------------------------+
                               |
                               | (Restricted Bridge Invocation)
                               v
+--------------------------------------------------------------+
|            Host Shell Capability Security Gateway            |
|  - Token Signature Validation                                |
|  - Namespace Isolation (Storage keys prepended: "checkout:") |
|  - Hardware Permission Checks (Camera, Geolocation)          |
|  - Transactional Bridge Rate Limiting                        |
+--------------------------------------------------------------+
                               |
                               | (Authorized Native Calls)
                               v
+--------------------------------------------------------------+
|                 Hardware & OS Native Modules                 |
|             (Secure Enclave, Camera, GPS, Push)              |
+--------------------------------------------------------------+

Implementing the Scoped Capability Proxy

import { createContext, useContext, ReactNode } from 'react';
import { NativeModules } from 'react-native';

interface ScopedSecurityBridge {
  getSecureItem: (key: string) => Promise<string | null>;
  setSecureItem: (key: string, value: string) => Promise<void>;
  trackAnalyticsEvent: (event: string, properties: Record<string, unknown>) => void;
  requestCameraAccess: () => Promise<boolean>;
}

export function createMiniAppBridge(miniAppNamespace: string): ScopedSecurityBridge {
  const { EncryptedStorageModule, AnalyticsModule, HardwarePermissionModule } = NativeModules;

  return {
    getSecureItem: async (key: string): Promise<string | null> => {
      // Enforce namespace sandboxing
      const scopedKey = `@miniapp_${miniAppNamespace}::${key}`;
      return await EncryptedStorageModule.getItem(scopedKey);
    },

    setSecureItem: async (key: string, value: string): Promise<void> => {
      const scopedKey = `@miniapp_${miniAppNamespace}::${key}`;
      await EncryptedStorageModule.setItem(scopedKey, value);
    },

    trackAnalyticsEvent: (event: string, properties: Record<string, unknown>): void => {
      AnalyticsModule.logEvent(`[${miniAppNamespace}] ${event}`, {
        ...properties,
        miniApp: miniAppNamespace,
        timestamp: Date.now(),
      });
    },

    requestCameraAccess: async (): Promise<boolean> => {
      // Capability check verified against host permissions policy
      return await HardwarePermissionModule.requestPermissionForScope(miniAppNamespace, 'CAMERA');
    },
  };
}

const BridgeContext = createContext<ScopedSecurityBridge | null>(null);

export const MiniAppBridgeProvider = ({
  namespace,
  children,
}: {
  namespace: string;
  children: ReactNode;
}) => {
  const bridge = createMiniAppBridge(namespace);
  return <BridgeContext.Provider value={bridge}>{children}</BridgeContext.Provider>;
};

export const useMiniAppBridge = () => {
  const ctx = useContext(BridgeContext);
  if (!ctx) {
    throw new Error('useMiniAppBridge called outside MiniAppBridgeProvider boundary.');
  }
  return ctx;
};

---

Inter-Module Communication, Navigation, and Push Notification Queues

Decoupling mini-apps into separate repositories requires standardized communication channels that avoid compile-time dependencies.

Rather than importing React component trees across module boundaries, navigation between mini-apps is mediated by universal URL schemes.

myapp://checkout/review?orderId=ORD-98421
myapp://marketplace/product?sku=SKU-1004

The Host Shell maintains a dynamic routing map. When a user navigates from the Marketplace mini-app to the Checkout mini-app, the routing controller delegates dynamically:

navigation.navigate('DynamicLoader', {
  screen: 'MiniCheckout',
  module: './CheckoutEntry',
  params: { orderId: 'ORD-98421' },
});

2. Centralized Push Notification Ingestion and Queuing

Push notifications arrive at a single native application endpoint managed by Apple Push Notification service (APNs) and Firebase Cloud Messaging (FCM). The Host Shell inspects incoming notification payloads and routes them through an internal event bus.

If a notification targets a mini-app that has not yet loaded into memory, the Host Shell queues the event in a persistent buffer:

type NotificationPayload = {
  targetMiniApp: string;
  route: string;
  data: Record<string, unknown>;
};

class SuperAppEventBus {
  private queue: Map<string, NotificationPayload[]> = new Map();
  private listeners: Map<string, (payload: NotificationPayload) => void> = new Map();

  public emitNotification(payload: NotificationPayload): void {
    const handler = this.listeners.get(payload.targetMiniApp);
    if (handler) {
      handler(payload);
    } else {
      // Mini-app not yet mounted; queue payload
      const existing = this.queue.get(payload.targetMiniApp) || [];
      this.queue.set(payload.targetMiniApp, [...existing, payload]);
    }
  }

  public registerConsumer(miniAppId: string, consumer: (payload: NotificationPayload) => void): () => void {
    this.listeners.set(miniAppId, consumer);

    // Flush queued payloads
    const pending = this.queue.get(miniAppId) || [];
    pending.forEach((payload) => consumer(payload));
    this.queue.delete(miniAppId);

    return () => {
      this.listeners.delete(miniAppId);
    };
  }
}

export const superAppBus = new SuperAppEventBus();

---

2026 Engineering Velocity and Operational Cost Model

Adopting a mobile micro-frontend architecture represents an architectural investment aimed at scaling engineering throughput while managing cloud distribution infrastructure.

When engineering executives architect high-throughput mobile platforms or transition legacy enterprise monoliths into distributed super-apps, our advisory practice provides end-to-end guidance and systems engineering. Explore how our team accelerates complex platform transformations through Wise Hustlers mobile development services.

Operational Cost Model: 500,000 Monthly Active Users (MAU)

To evaluate distribution economics, consider an enterprise deployment profile serving dynamic mini-apps across a user base of 500,000 MAU.

  • Modeled Operational Parameters:

* Monthly Active Users (MAU): 500,000

* Daily Active Users (DAU): 150,000 (30% DAU/MAU ratio)

* Average Compressed Mini-App Bundle Size: ~350 KB (Brotli compressed, excluding shared singletons)

* Mini-App Deployment Cadence: 4 bundle updates per month across 5 independent mini-apps

* CDN Edge Cache Hit Ratio: 88% (client-side ETags prevent re-downloading unchanged bundles)

  • Data Transfer Estimations:

* Total Mini-App Session Launches: 150,000 DAU Γ— 3 mini-app views/day = 450,000 daily launches

* Uncached Manifest & Bundle Requests: 450,000 Γ— (1 - 0.88) = 54,000 bundle downloads/day

* Monthly Edge Bundle Downloads: 54,000 Γ— 30 days = 1,620,000 requests/month

Monthly Bandwidth Egress: 1,620,000 requests Γ— 350 KB β‰ˆ 567 GB/month

Infrastructure ComponentAWS CloudFront + S3 (Standard Tier)Cloudflare R2 + CDN
Object Storage (~5 GB versioned bundles)~$0.12 / month~$0.08 / month
Storage API Operations (Class A/B)~$3.50 / month~$1.20 / month
Bandwidth Egress (567 GB)~$48.20 / month (Standard $0.085/GB rate)$0.00 / month (Zero Egress Model)
Estimated Monthly Delivery Cost~$51.82 / month~$1.28 / month

(Cost Note: AWS CloudFront includes an Always-Free Tier covering up to 1 TB of data transfer out per month for qualifying accounts per [AWS CloudFront Pricing](https://aws.amazon.com/cloudfront/pricing/). The table above illustrates standard baseline billing rates at $0.085/GB for accounts where free tier allowances are exhausted or enterprise billing pools apply, alongside standard object storage fees per [AWS S3 Pricing](https://aws.amazon.com/s3/pricing/). In contrast, [Cloudflare R2 Pricing](https://www.cloudflare.com/developer-platform/r2/) eliminates data egress fees entirely).

Cloud delivery expenses remain modest relative to overall development capacity. The strategic value of the architecture lies in decoupling delivery streams and eliminating synchronization bottlenecks inherent in monolithic release trains.

Engineering Delivery Cadence Comparison:
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Operational Dimension           β”‚ Monolithic Release Trainβ”‚ Re.Pack Super-App       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Deployment Cadence              β”‚ Scheduled sprint trains β”‚ Continuous sub-squad OTAβ”‚
β”‚ Cross-Squad Coordination        β”‚ High (release freezes)  β”‚ Low (contract testing)  β”‚
β”‚ App Store Review Gate           β”‚ Full binary submission  β”‚ Native shell changes onlyβ”‚
β”‚ Emergency Hotfix Propagation    β”‚ Hours to days (binary)  β”‚ Immediate bundle update β”‚
β”‚ CI/CD Pipeline Scope            β”‚ Full monolithic suite   β”‚ Scoped mini-app suite   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

According to empirical findings from the DORA (DevOps Research and Assessment) State of DevOps research, organizational delivery performance correlates strongly with decoupled architectures and smaller batch sizes. In a multi-squad mobile organization, eliminating the need to coordinate release trains across every domain squad directly reduces lead time for changes and minimizes developer idle time caused by merge freezes and release blocker triage. Rather than forcing independent feature teams into a single release train, Module Federation allows squads to release features at their own cadence while keeping the host application resilient.

---

Comprehensive Architectural Comparison: Monolith vs. Module Federation vs. WebViews

Choosing between native compilation, dynamic Module Federation, and embedded web micro-frontends requires evaluating trade-offs across performance, security, and developer ergonomics.

Architectural DimensionMonolithic React NativeRe.Pack Module FederationEmbedded WebViews (Micro-Web)
Compilation EngineMetro BundlerRspack via Re.Pack v5Vite / Webpack / Next.js
Deployment VelocityScheduled binary release trainOver-the-air CDN deploymentInstant web deploy
UI Thread Performance60–120 FPS native Fabric views60–120 FPS native Fabric views30–60 FPS (DOM thrashing risks)
App Store Review ProcessStandard native review on every updateNative review on host updates; OTA within Guideline 2.5.2Standard web hosting
Native Hardware AccessDirect access to all native APIsMediated via Capability GatewayRestricted through web bridge
Offline ExecutionAvailable from initial installManaged via local disk cache and fallback engineComplex Service Worker caching
Binary Size OverheadGrows with overall codebase sizeLean host shell baselineLean host shell baseline
Crash Blast RadiusSingle squad bug can crash whole appIsolated via React Error BoundariesWeb process crash; shell intact

---

Frequently Asked Questions

Does dynamic bundle loading via Module Federation violate Apple App Store Review Guideline 2.5.2?

Dynamic bundle delivery via Module Federation aligns with standard enterprise over-the-air update patterns when implemented within App Store boundaries. Under Section 2.5.2 of the Apple App Store Review Guidelines, applications may execute dynamic code that is interpreted by an approved engine (such as JavaScript evaluated in the Hermes VM), provided that the updates do not alter the fundamental purpose or category of the application as approved in App Store Connect. Additionally, digital goods and premium digital services must strictly route through Apple In-App Purchase APIs under Guideline 3.1.1. Dynamic loading must be used for feature updates, bug fixes, and domain workflows consistent with the application's stated purpose, rather than bypassing App Store review to deliver unrelated business models.

How do you prevent version mismatches between shared dependencies like React and React Native?

Module Federation enforces version locks using the shared configuration object. By defining singleton: true, eager: true, and strict requiredVersion semver strings in both the Host Shell and Mini-App configurations, the host guarantees that only one instance of React runs inside Hermes. In development and CI pipelines, automated contract checks verify that all mini-apps compile against compatible peer dependency versions before releasing bundles to the CDN.

What is the memory and cold-start performance impact of loading multiple remote bundles with Hermes?

Hermes is designed specifically to optimize React Native start-up time and runtime memory footprint. In a Module Federation architecture, shared dependencies (such as React, React Native runtime libraries, and core design tokens) are loaded eagerly by the Host Shell as singletons and remain resident in memory. As a result, dynamically mounting an individual remote mini-app introduces incremental memory overhead primarily for the mini-app's own component tree, assets, and local state. Furthermore, Hermes supports pre-compiled bytecode (hermesc) and bytecode caching, which substantially reduces on-device parsing overhead compared to standard JavaScript interpretation. Teams can profile memory and cold-start metrics using React Native Performance Monitor and native profilers (Xcode Instruments and Android Studio Profiler) across target hardware tiers.

How does the host shell handle breaking native module changes when a mini-app requires a newer native library?

When a mini-app requires a new native capability (such as a specialized biometric library or updated Bluetooth protocol), that capability cannot be delivered dynamically via JavaScript over a CDN. The Host Shell must release an updated native binary to the App Store. The host's manifest.json schema specifies a minHostVersion constraint. If an older host binary encounters a mini-app requiring an unsupported native bridge version, the client state machine suppresses the dynamic update and displays a banner advising the user to update the host app from the App Store.

---

Sources

Related articles