DEV Community

motion team for Motion

Posted on

We Thought React Native Was the Answer... Until Our App Hit 190% CPU πŸ”₯πŸ“±

TL;DR: React Native seemed perfect for our productivity app until performance became unbearable. Here's why we switched to native and the dramatic results we achieved.


The Breaking Point πŸ’”

Our React Native desktop app was consuming 190% CPU for a simple productivity tool. Users complained about:

  • Severe battery drain πŸ”‹
  • Fan noise from overheating 🌑️
  • Sluggish system performance 🐌
  • App crashes under load πŸ’₯

What We Found πŸ”

1. Bridge Tax
Every JS ↔ Native call adds overhead:

///Each call crosses the expensive bridge
const windows = await nativeModules.getWindows();
const activeApp = await nativeModules.getActiveApplication();
Enter fullscreen mode Exit fullscreen mode

2. Re-rendering Hell
Components re-rendering 60+ times per second:

const TaskList = ({ tasks, filters, sortBy }) => {
  const filteredTasks = useMemo(() => {
    return tasks.filter(/* expensive filtering */)
  }, [tasks, filters, sortBy]); // Dependencies changing constantly
};
Enter fullscreen mode Exit fullscreen mode

3. Memory Leaks in Native Modules
Poor resource cleanup in custom modules.


The Numbers Don't Lie πŸ“Š

React Native vs Native Performance:

  • CPU Usage: 190% β†’ 15%
  • Memory: 400MB β†’ 100MB
  • Cold Start: 3.2s β†’ <1s
  • Battery Impact: High β†’ Minimal

The Native Solution πŸš€

We rebuilt using Swift/SwiftUI with performance-first design:

//Efficient window monitoring
class WindowMonitor: ObservableObject {
    private var eventTap: CFMachPort?

    func startMonitoring() {
        eventTap = CGEvent.tapCreate(
            tap: .cgSessionEventTap,
            place: .headInsertEventTap,
            options: .defaultTap,
            eventsOfInterest: CGEventMask(eventMask),
            callback: { /* efficient callback */ }
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

Results 🌟

  • CPU usage: 190% β†’ 15% πŸ“‰
  • Memory: 75% reduction πŸ—œοΈ
  • Launch time: 60% faster ⚑
  • Silent operation (no more fan noise!)

When to Choose What πŸ’‘

React Native is great for:

  • Content-heavy apps
  • Standard UI patterns
  • Rapid prototyping
  • React-heavy teams

Go native when you need:

  • Performance-critical apps
  • Heavy system integration
  • Resource efficiency
  • Background processing

The Bottom Line 🎯

React Native isn't badβ€”it's just not right for every use case. For Motion's requirements (system integration, background processing, resource efficiency), native was the clear winner.

The key is recognizing when to make the switch before performance problems become user complaints.


Read the full technical deep-dive: Motion Engineering Blog

Building high-performance productivity software at Motion. We're always looking for talented engineers who care about performance and user experience. Join our team!

Top comments (0)