Summary
React Native Nitro and TurboModule are both native module methods that emerged to reduce the bottleneck between JavaScript and native code. However, the location is different. TurboModule is the official native module system of React Native New Architecture, and Nitro Modules is a third-party framework that aims to provide more object-oriented and faster native binding on top of JSI. In this article, we will explain what TurboModule and Nitro are, what criteria should be used to select them in an actual project, and the points that often get stuck when introducing them.
Table of Contents
- Background
- What Is TurboModule?
- What Are Nitro Modules?
- TurboModule vs. Nitro
- Selection Criteria
- Common Confusion and Fixes
- Best Practices
- FAQ
- Conclusion
- References
- Related Posts
Background
If you use React Native for a long time, you will eventually encounter areas that are difficult to handle with JavaScript alone. Representative examples include camera frame processing, encryption, local database, sensor, BLE, image/audio processing, and platform-specific SDK integration. At this time, the React Native app must call the native API from JavaScript.
In the past, the Legacy Native Module serialized and exchanged data through an asynchronous bridge between JavaScript and native. It was sufficient for general app functions, but it was a burden for large binary data or native functions that were called very frequently. React Native New Architecture introduced foundations such as Fabric, TurboModule, Codegen, and JSI to reduce this limitation.
As of June 18, 2026, npm’s react-native The latest version is 0.86.0The official React Native document explains how New Architecture is activated by default starting from 0.76. The latest version of npm for Nitro Modules is react-native-nitro-modules@0.35.9confirmed. Since this is an area where versions change quickly, it is safer to check the React Native version of the current project and the requirements of the libraries used before actual introduction.
What Is TurboModule?
TurboModule is the official way to create native modules in React Native New Architecture. There are three key points.
1. Declare the interface of the native module with TypeScript or Flow. 2. React Native Codegen reads this declaration and creates a native interface for Android/iOS. 3. The developer implements the created interface and calls it in JavaScript like a typed API.
Simply put, TurboModule is “a type-based native module system provided by the React Native core.” An example from the official documentation is NativeLocalStorage After declaring the same module as TypeScript spec, Android SharedPreferences, on iOS NSUserDefaultsIt shows the implementation flow.
// NativeLocalStorage.ts 예시 형태
import type {TurboModule} from 'react-native';
import {TurboModuleRegistry} from 'react-native';
export interface Spec extends TurboModule {
getItem(key: string): string | null;
setItem(value: string, key: string): void;
removeItem(key: string): void;
clear(): void;
}
export default TurboModuleRegistry.getEnforcing<Spec>('NativeLocalStorage');
The advantage of TurboModule is its official support. Because it is part of the React Native core, it is not strongly dependent on a separate runtime framework. The direction taken with the New Architecture is clear, and most library compatibility discussions are conducted on the TurboModule/Fabric basis.
However, “formal method” does not mean “simplest.” There is an initial entry barrier when codegen settings, Android/iOS build settings, whether New Architecture is enabled, and the boundaries of C++/Objective-C++/Java/Kotlin are intertwined. In particular, those distributing libraries must decide whether to support the previous Legacy Architecture or only the New Architecture.
What Are Nitro Modules?
Nitro Modules is a React Native native module framework created by Marc Rousavy of Margelo. Although it is not an official React Native core feature, it aims to provide fast and type-safe native binding based on JSI.
The core concept of Nitro is Hybrid Objectall. While TurboModule usually exposes a single module as a singleton API, Nitro emphasizes a model in JavaScript that creates native objects like regular objects and calls methods and properties.
// Math.nitro.ts 예시 형태
import type {HybridObject} from 'react-native-nitro-modules';
export interface Math extends HybridObject<{ios: 'swift'; android: 'kotlin'}> {
readonly pi: number;
add(a: number, b: number): number;
}
import {NitroModules} from 'react-native-nitro-modules';
import type {Math} from './specs/Math.nitro';
const math = NitroModules.createHybridObject<Math>('Math');
const result = math.add(5, 3);
Nitro is nitrogenIt generates C++, Swift, and Kotlin bindings from TypeScript interfaces through a code generator called . iOS uses Swift and C++ interop to reduce the number of passes through Objective-C, and Android supports Kotlin/Java and C++ interop.
Nitro’s official documentation explains that Nitro showed faster results than TurboModule in a benchmark that calls a single native method 100,000 times. However, this figure is the result of an extreme comparison of “native method call throughput,” and actual app performance varies depending on other bottlenecks such as rendering, network, data structures, disk I/O, and JS logic. So when choosing Nitro, you should not just look at the benchmark numbers, but first ask, “Is my app really bottlenecked at the native call boundary?”
TurboModule vs. Nitro
| Category | TurboModule | Nitro Modules |
|---|---|---|
| Position | React Native Official New Architecture Components | JSI-based third-party framework |
| Code Generation | React Native Codegen | Nitrogen |
| API Model | Module/function oriented, usually used like a singleton | Hybrid Object-centered, emphasizing object and property models |
| iOS Implementation | There are many Objective-C/Objective-C++ based examples, and Swift requires separate bridging consideration. | Actively utilizes Swift 5.9+ and C++ interop |
| Android Implementation | Java/Kotlin/C++ available | Kotlin/Java/C++ available |
| Strengths | Formality, ecosystem standards, long-term compatibility | High-performance calls, object model, type safety, Swift/Kotlin friendly design |
| Cautions | Setting up Codegen and New Architecture can be tricky | Need to check separate dependencies, minimum requirements, and rapidly changing API/build issues |
TurboModule fits the basic direction of the React Native project. If you say, “I need to create a native module, but I want to go the official way,” it’s natural to look at TurboModule first.
Nitro is attractive for libraries where performance and object model are important. For example, Nitro’s Hybrid Object method may be a good fit for a model where “native objects are constantly carried and manipulated on the JavaScript side,” such as image objects, frame objects, database handles, and audio buffers.
Selection Criteria
If you want to lightly call a native API inside an app, look at TurboModule first.
If your app only calls a few platform APIs, TurboModule is generally a safer default. This is because changes in React Native official documentation and release notes are explained based on TurboModule and are part of the New Architecture.
For example, if the call frequency is not high and the return data is simple, such as saving app settings, simple device information inquiry, or calling an internal SDK, TurboModule is often sufficient.
If you are building a library and need a high-performance object model, consider Nitro.
Conversely, if the library creator wants to expose native objects directly to JavaScript, or if too many native calls are a performance bottleneck, Nitro may be worth considering. Nitro’s development experience may be particularly attractive to teams looking to write modern native code in Swift/Kotlin.
However, Nitro is not a React Native core feature. Therefore, the build environment requirements, version compatibility, and issue response costs that the team must bear must be considered together.
If you are only looking at Expo Managed Workflow, check library compatibility first.
Native modules may be required in Expo apps, but adding native code may be limited in Managed Workflow. Access varies depending on whether it is Expo Dev Client, config plugin, or prebuild. If you want to use a Nitro or TurboModule-based library, you must first check how the library supports the Expo environment.
Common Confusion and Fixes
Case 1. New Architecture is turned on, but TurboModule is not loaded.
Symptoms usually look like this:
TurboModuleRegistry.getEnforcing(...): 'NativeSomething' could not be found
In this case, first “JavaScript spec name”, “Native module name”, “Codegen settings” name/jsSrcsDir” and “Package Registration” check if they match.
{
"codegenConfig": {
"name": "NativeLocalStorageSpec",
"type": "modules",
"jsSrcsDir": "specs",
"android": {
"javaPackageName": "com.nativelocalstorage"
}
}
}
The common sticking point here is the spec file location and module name. TurboModuleRegistry.getEnforcing<Spec>('NativeLocalStorage')Strings used in and native implementations of NAMEIf this is different, the runtime will not find the module. In many cases, you need to clean build each Android/iOS for the generated code to be reflected.
Case 2. Codegen does not handle TypeScript types
In React Native GitHub issues, there continue to be cases where Codegen behaves differently than expected when handling some imported types, complex unions, and map/null. Not all TypeScript expressions translate naturally to native bindings.
The first step to solving this problem is to simplify the spec.
// 피하는 편이 안전한 형태: 외부 파일에서 복잡한 타입을 import해서 바로 사용
import type {ExternalComplexType} from './types';
export interface Spec extends TurboModule {
save(value: ExternalComplexType): void;
}
// 더 안전한 형태: Codegen이 이해하기 쉬운 구조로 spec 경계를 단순화
export type SavePayload = {
id: string;
name: string;
count?: number;
};
export interface Spec extends TurboModule {
save(value: SavePayload): void;
}
By clearly defining only the necessary values at the native boundary rather than passing complex objects as is, build errors and platform-specific differences can be reduced.
Case 3. iOS/Android build is broken after installing Nitro
Nitro relies on the latest JSI, C++, Swift/Kotlin, and NDK/Xcode environments. Based on official documentation, Nitro requires React Native 0.75 or higher, iOS requires Xcode 16.4 or higher and Swift 5.9 or higher, and Android requires compileSdkVersion Requires 34 or higher and NDK 27 or higher.
First, check below.
node -v
npm view react-native version
npm view react-native-nitro-modules version
On Android compileSdkVersion, ndkVersion, check the CMake/Gradle log, and on iOS, you should see the last error in the actual failed compilation log in Xcode Report Navigator. “BUILD FAILED” alone does not determine the cause.
In particular, looking at Nitro GitHub issues, native build layer issues such as Swift C++ interop, generated header conflict, and Android NDK/16KB page size appear. This problem is difficult to solve just by looking at the JavaScript code. If it breaks even after meeting the minimum requirements, it is quick to find the issue by organizing the actual error line in all logs and the React Native/Nitro/Xcode/NDK version being used.
Best Practices
Make native boundaries small and clear
Whether TurboModule or Nitro, the API between JavaScript and native should be small and clear. It is more advantageous for debugging and type maintenance to pass only the necessary values in native rather than passing the entire JS object.
Measure performance issues first
Just because Nitro provides fast benchmarks doesn’t mean every app should switch to Nitro. You must first measure whether the native call is the bottleneck, rendering is the bottleneck, or DB query is the bottleneck. For functions that are called less frequently, TurboModule’s formality and maintainability may be a bigger advantage.
Check the New Architecture support status when selecting a library.
As the basic activation flow of New Architecture has been strengthened since React Native 0.76, old native libraries may have problems in build or runtime. When selecting a library, you should check README for New Architecture support, latest release date, open issues, and RN version compatibility range.
FAQ
Are TurboModule and Nitro substitutes for each other?
It is not completely the same layer of technology. TurboModule is React Native’s official native module system, and Nitro is a separate framework that provides faster, object-oriented binding on top of JSI. TurboModule is natural for simple app internal modules, and Nitro may be more suitable for libraries that require a high-performance object model.
Can I use TurboModule even if I turn off React Native New Architecture?
In general, it is correct to think of TurboModule along with the New Architecture flow. The official document distinguishes between Turbo Native Module examples dedicated to New Architecture and separate compatibility guides that support Legacy Architecture. If an existing app needs to support both, a compatibility layer must be designed separately.
If I use Nitro, will the app always be faster?
no. Nitro’s strengths lie in its native call boundaries and object model. If the app’s bottleneck is rendering, network, server response, DB design, or JS state management, the perceived performance may not change significantly even if Nitro is introduced.
If I’m creating a new React Native library, which one should I choose?
If long-term compatibility with the official ecosystem is your top priority, consider TurboModule first. On the other hand, if it is a library that continues to deal with native objects such as image/video/audio/frame processing and is frequently called, Nitro is a worthy candidate. However, the team must be able to view Swift C++ interop, Android NDK, and CMake logs to handle the operational burden.
Conclusion
In React Native, TurboModule is closer to the “official New Architecture native module standard,” and Nitro Modules is closer to the “JSI-based high-performance object binding framework.” Both have the same direction of reducing the limitations of the bridge era, but the selection criteria are different.
If you’re connecting a simple native API inside your app, it’s safer to start with TurboModule. On the other hand, if you need to carry native objects in JavaScript for a long time and call them frequently, or if you strongly require performance and type safety at the library level, Nitro is worth considering. The important thing is not to choose based solely on the technology name, but also to look at the current project’s React Native version, build environment, team’s native debugging capabilities, and actual performance bottlenecks.
References
- React Native official documentation – About the New Architecture: https://reactnative.dev/docs/the-new-architecture/landing-page
- React Native official documentation – Native Modules: Introduction: https://reactnative.dev/docs/turbo-native-modules-introduction
- React Native Blog – New Architecture is here: https://reactnative.dev/blog/2024/10/23/the-new-architecture-is-here
- React Native 0.75 release notes: https://reactnative.dev/blog/2024/08/12/release-0.75
- Nitro Official Documentation – What is Nitro?: https://nitro.margelo.com/docs/getting-started/what-is-nitro
- Nitro Official Documentation – Comparison: https://nitro.margelo.com/docs/resources/comparison
- Nitro Official Documentation – Minimum Requirements: https://nitro.margelo.com/docs/getting-started/minimum-requirements
- Nitro GitHub repository: https://github.com/mrousavy/nitro
- React Native GitHub issue search – TurboModule Codegen: https://github.com/react/react-native/issues?q=TurboModule+Codegen
- Search Nitro GitHub issues – build/NDK/Xcode: https://github.com/mrousavy/nitro/issues
Related Posts
- What is SQLite? Advantages, limitations, and practical usage of file-based database without server: https://daily-it.duckdns.org/en/2026/06/19/sqlite-local-database-guide-en/
- What is WatermelonDB in React Native? How to use offline-first local DB compared to SQLite: https://daily-it.duckdns.org/en/2026/06/19/watermelondb-react-native-sqlite-guide-en/