Cross-Platform App Performance: Where Time Actually Goes

Cross-Platform App Performance: Where Time Actually Goes — T-Square engineering blog

TL;DR — Cross-platform app performance investigations find time in four places: bridge cost (much less in 2026), render commits, native module initialization and image decoding. Image work is usually the easiest win.

Cross-platform app — where the time actually goesImage decoding dominates startup time for most teams. Bridge cost is mostly historical post-New Architecture. — /startup time profile image decoding ~45% render commits ~20% native module init ~16% JS parse + eval ~12% bridge (legacy) ~7% → FastImage / expo-image · resize at source · decode off-thread
Image decoding dominates startup time for most teams. Bridge cost is mostly historical post-New Architecture.

“My React Native app is slow” is the start of a profiling session, not the end. The actual question is “where is the time going?” — and the answer is usually in places teams do not check first.

The four time sinks

1. Bridge cost (mostly historical)

The legacy JS-to-native bridge cost matters in old RN apps. With the New Architecture (Fabric + TurboModules), bridge cost is dramatically lower. If your app is on RN 0.74+ with New Architecture enabled, look elsewhere first.

2. Render commits

Re-renders propagate. A parent re-rendering triggers children. Add memo on leaves, hoist state down, and use useCallback / useMemo where they actually help. Profile with the React DevTools Profiler before adding them — many memoizations are useless.

3. Native module initialization

Every native module you import runs init code at app launch, even modules you never use on the current screen. Audit your dependency list. Move heavy modules behind lazy imports tied to specific screens.

4. Image decoding

The biggest single win in most apps. Images are loaded at original size, decoded on the main thread, and held in memory. Use FastImage or expo-image, decode off-thread, and resize at the source — not at render time.

The profiling order we follow

  1. Cold start trace — Hermes profile from cold boot to interactive
  2. Image audit — every <Image /> in the critical path checked for size, format, decoder
  3. Render audit — find the parent that re-renders on every state change
  4. Native module audit — count modules imported, dependency-tree their init cost
  5. Animation audit — make sure animations run on the UI thread (Reanimated worklets, not JS)

Skip steps and you optimize the wrong thing. We have seen teams rebuild navigation libraries to chase a bug that was an image-decoding stall.

Frequently asked questions

Is the bridge still a problem in 2026?

Not as much. With the New Architecture (Fabric + TurboModules) the legacy bridge is gone. Most “RN is slow” complaints from before 2025 do not apply to current builds.

What single optimization gives the biggest win?

Image handling. Most apps under-optimize images — wrong size, wrong format, decoded on the main thread. Fixing this alone often takes startup time down 20-40%.

Working on something similar?

T-Square architects, builds and operates production systems for learning, AI and custom software products. Talk to a senior engineer for a second opinion.

— /more

Keep reading