This article is published in English.
Nitro Modules: How Static Bindings Outperform React Native TurboModules
Explains how Nitro Modules use precompiled static bindings instead of dynamic lookups to dramatically outperform TurboModules and Expo Modules in React Native.
TurboModules were supposed to be the answer. They replaced the aging bridge architecture, trimmed away unnecessary overhead, and settled in as the accepted approach for writing native code that talks to JavaScript. Then a newer library called Nitro Modules arrived and made that "final answer" look outdated.
Published benchmarks show that when the identical synchronous function call is tested, Nitro Modules can outperform Expo Modules by a factor as high as 59, and outperform TurboModules by roughly 15 times. Even when strings are involved, which typically add overhead when crossing between JavaScript and native code, Nitro still holds a lead of 5 to 13 times. When you move larger payloads such as images or raw buffers, Nitro picks up another 8 to 40 percent improvement, thanks to a zero copy approach that avoids duplicating data in memory.
Numbers on that scale demand an explanation. What exactly is Nitro doing under the hood, and why didn't this design show up sooner?
The problem nobody else had solved
Nitro wasn't designed as a benchmark exercise. It came out of work by Marc Rousavy, creator of VisionCamera, in response to a very concrete limitation: neither TurboModules nor Expo Modules could properly support frame processing.
Think of a single camera frame in VisionCamera as something like a 10 megabyte buffer. That buffer can't be copied across the bridge, even using TurboModules, and it doesn't fit into a plain JSON-like structure either. What Rousavy actually needed was a way to hand a complex, stateful native object, written in C++ or Swift, over to JavaScript directly, complete with working methods and properties. TurboModules had no mechanism for that kind of object.
So Nitro was built specifically to make that possible, and the dramatic speed gains turned out to be a bonus that ended up drawing far more attention than the original problem it solved.
A single architectural choice
The real gap between TurboModules and Nitro comes down to one design decision: how each system represents a native object once it's inside the JavaScript engine.
TurboModules rely on jsi::HostObject. Whenever JavaScript code accesses a property or invokes a method on one of these objects, the runtime has to resolve that access dynamically, on the spot. This lookup happens on every single call, and that repeated cost adds up quickly for modules that get invoked often.
Nitro takes a different route, using jsi::NativeState. Paired with a code generation tool called Nitrogen, it produces all the necessary C++, Swift, or Kotlin bindings ahead of time, before the app is ever run. Nothing is resolved dynamically at runtime. The conversion between JavaScript and native types is compiled statically in advance, which means invoking a Nitro module behaves more like calling an ordinary function than crossing a runtime bridge.
That one shift, precompiled static bindings in place of dynamic runtime lookups, accounts for most of the performance gap shown in the benchmarks.
Within Nitro, any native object, whether written in C++, Swift, or Kotlin, is referred to as a Hybrid Object. Nitrogen parses a TypeScript interface definition and automatically generates the code required to move that object across the JS-native boundary, including handling for enums, unions, and structs. This tooling is exactly what allowed Rousavy to expose something as unconventional as a live camera frame, without manually writing separate bridging code for each of the three platforms.
Why this reaches beyond a single library
VisionCamera served as the initial proof that this approach worked, but Nitro's design was never meant to remain a one-off solution for a single use case. Its architecture gives any native module built-in support for array buffers, stateful native objects, and direct C++ interop, capabilities that were clunky at best, or outright unworkable, under the previous approaches.
The wider React Native ecosystem has started to take notice. Projects such as react-native-nitro-cache, alongside tools aimed at image caching, machine learning workloads, and game engines, are being rebuilt on top of Nitro specifically to cut down JavaScript-to-native overhead in the paths where performance matters most. This mirrors a larger trend already underway across React Native, where foundational libraries are being restructured around the New Architecture rather than treating it as something optional to adopt later. Nitro's adoption is still well behind TurboModules, which continues to be the default choice for the majority of libraries, but the trajectory is unmistakable. Wherever raw performance is the priority, Nitro is increasingly the first tool developers reach for.
What this means for native module authors
If you currently maintain a native module, this shift deserves your attention. TurboModules aren't disappearing anytime soon, and for straightforward modules, the performance gap likely won't be noticeable to end users. But if your module involves anything performance sensitive, high call frequency, large data payloads, or objects that don't map cleanly onto JSON, Nitro is now very likely the stronger foundation to build on.
Choosing to start a brand-new native module on TurboModules in 2026 effectively means building on an architecture that a faster, still-growing alternative has already surpassed. Nitro's code generator handles far more of the repetitive work automatically across all three platforms simultaneously, and what comes out the other end runs faster while requiring less hand-written native code to maintain. For teams with an existing TurboModule, migration isn't a trivial flip of a switch, but the same benchmark results that make Nitro appealing also build a strong case for scheduling that migration sooner rather than later.
React Native has already lived through a handful of genuine architectural turning points: the retirement of the bridge, the introduction of the New Architecture, and now this one. Nitro didn't show up backed by an official mandate from Meta. It showed up because one developer needed a capability that TurboModules simply couldn't provide, built the solution in public, and let the resulting benchmarks speak for themselves.