JSI: What It Is, How It Works, and Architecture

Author: IT Sectr Published: 2026-06-04 Reading time: 10 min

JSI (JavaScript Interface) is a software layer in React Native that provides direct synchronous access from JavaScript to C++ objects and functions, replacing the asynchronous JSON bridge. Unlike its predecessor, JSI allows calling native methods without message serialization and passing references to C++ objects directly into the JS environment. According to React Native Team (2025), JSI delivers up to 10x acceleration of JS-to-native code interaction in data-intensive scenarios.

Key Takeaways

  • JSI — JavaScript Interface providing synchronous access from JS to native C++ code
  • Direct access eliminates the need for JSON serialization and asynchronous message queue
  • Performance of JS and native code interaction increases by 5–10x
  • Architecture JSI is the foundation of Fabric and TurboModules in the new React Native architecture
  • C++ integration allows connecting arbitrary C++ libraries without native wrappers

What is JSI?

JSI (JavaScript Interface) is a C++ layer that provides the JavaScript engine (Hermes, JavaScriptCore, V8) with the ability to directly access C++ objects, functions, and memory. Unlike Bridge, which serialized calls into JSON and passed them through an asynchronous queue, JSI allows JS code to synchronously call C++ methods and get the result immediately.

JSI was introduced in React Native 0.64 as part of the New Architecture. The main goal was to eliminate the bottleneck that Bridge represented: each interaction between JS and native code consumed time on serialization, deserialization, and passing through the message queue. JSI solves this problem by giving the JS engine direct access to C++ objects through wrappers implementing the jsi::Value, jsi::Object, and jsi::Function interfaces.

JSI is not a one-to-one replacement of Bridge — it is a fundamentally different approach to integration. Bridge worked like a mailbox: JS sent a message, it passed through a queue, the native side processed it and sent a reply. JSI works like a pointer: JS gets a reference to a C++ object and can call its methods synchronously, just like regular JS functions. This is a fundamental difference in the architecture of interaction between two environments.

History of Creation

The need for JSI arose from the limitations of the original Bridge, established in React Native 2015. As the framework grew in popularity and applications became more complex, the performance problem became apparent: each native module call required at least 3–5 ms for serialization. For simple operations like reading a sensor value or getting screen size, this was acceptable, but for animations, graphics work, and streaming data processing — it was critical. The React Native team began work on the new architecture in 2019, and JSI became its foundation.

JavaScript Engine Support

JSI is designed as an abstraction layer over JavaScript engines. It provides a unified C++ API that is implemented for each specific engine: Hermes, JavaScriptCore (iOS), V8 (Android). This means developers don’t need to worry about differences between engines — Fabric and TurboModules work the same regardless of which JS engine is used under the hood.

How Does JSI Work?

At the core of JSI lies the concept of Host Objects — C++ objects that are exported to the JS environment as native JS objects. When JS code accesses a property or method of such an object, JSI intercepts the call and delegates it to the corresponding C++ method. This happens synchronously, in the same thread, without context switching and without allocating memory for a JSON string.

Each Host Object implements the jsi::HostObject interface with get, set, and getPropertyNames methods. The JS engine calls these methods every time a property of the object is accessed. For example, when calling NativeModule.someMethod() in JS, JSI converts this call into a C++ call to the corresponding Host Object method. The return value is passed back to JS as a jsi::Value — a generic type that can represent a number, string, boolean, object, or undefined.

An important feature of JSI is the absence of a message queue. Bridge used an asynchronous queue: JS sent a request, switched to other tasks, the native side processed the request, and the result was returned via a callback. JSI works synchronously: if JS calls a native module method through JSI, JS code execution pauses until the result is received. This simplifies logic (no need to wait for callbacks) and eliminates race conditions, but requires caution — long synchronous calls block the JS thread.

Lifecycle of JSI Values

Values created through JSI live in the JS engine runtime and are managed by the garbage collector. When C++ code creates a jsi::String or jsi::Object and returns it to JS, the environment automatically manages memory. If C++ code wants to keep a reference to a JS value between calls, jsi::Value::getWeak() or a global jsi::Object::setProperty with a reference stored on the runtime root object is used. This prevents premature garbage collection.

Thread Safety

JSI is not thread-safe by default. All JSI method calls must occur from the thread where JS executes (usually the JS thread of React Native). If a native module starts background work on a separate thread, the result must be passed back through the JS thread using runOnJS from TurboModules. This limitation is the price for synchronicity and the absence of serialization.

JSI vs Bridge: Comparison

The difference between JSI and Bridge is fundamental and affects all aspects of JS-to-native code interaction. Bridge was asynchronous, serialized data to JSON, and used a message queue; JSI is synchronous, works with native references, and requires no serialization.

ParameterBridgeJSI
Call ModelAsynchronous queueSynchronous direct call
SerializationJSON (serialization + deserialization)None (direct references to C++ objects)
Latency3–10 ms per call0.1–0.5 ms per call
TypingDynamic (via JSON)Static (via Codegen)
C++ IntegrationOnly through native modules (Java/ObjC)Direct, no intermediaries
ThreadSeparate native threadJS thread (synchronous)

According to React Native Team, migrating from Bridge to JSI in the Facebook Marketplace app reduced startup time by 35% and decreased memory consumption by 20% by eliminating data duplication between JS and native sides.

When Bridge Was Necessary

Bridge was not a “mistake” — it was an architectural decision justified at the time of React Native’s creation in 2015. Native development for two platforms with different languages required a universal exchange format. JSON as a serialization format was available on all platforms and allowed unifying the interaction. The problem became apparent later, when React Native began to be used for complex applications with thousands of native module calls per second.

Backward Compatibility

React Native maintains backward compatibility: native modules written for Bridge continue to work in the new architecture through a compatibility layer. However, for new modules, it is recommended to use JSI directly through TurboModules. Migrating existing modules involves replacing the interaction protocol without changing the business logic of the module itself.

JSI in React Native Architecture

JSI is a fundamental layer on which all components of the new React Native architecture are built. Without JSI, neither Fabric (the new renderer) nor TurboModules (optimized native modules) would be possible. JSI provides a unified way for JS to interact with C++ at all levels.

Fabric and JSI

Fabric is the new React Native renderer that uses JSI for synchronous access to C++ UI representations. In the old architecture, rendering went through Bridge: JS created React elements, serialized them to JSON, sent them through Bridge, the native side deserialized and created the UI. Fabric through JSI creates C++ Shadow Tree objects directly from JS, synchronously computes Layout via Yoga and passes ready frames to the native renderer — without a single serialization.

TurboModules and JSI

TurboModules are the evolution of React Native native modules. Instead of registering a module in Bridge and calling its methods through JSON, TurboModules uses JSI for lazy loading and direct invocation. When JS code first accesses a module, JSI creates a Host Object — it loads the native module and exposes its methods as C++ functions. Lazy loading means the module does not consume memory until first access — this is especially important for applications with dozens of native modules, many of which are only used in specific screens.

Code Generation through JSI

To work with JSI in the new architecture, Codegen is used — a tool that generates C++ bindings from JavaScript specifications. The developer describes the native module interface in TypeScript or Flow, and Codegen generates C++ code implementing a JSI-compatible Host Object. This automates routine work and guarantees that types on the JS and C++ sides are synchronized.

JSI Code Examples

Let’s look at how working with JSI looks in practice. In this example, we create a simple C++ class that is exported to JS through JSI, and call its method from JavaScript code in React Native.

cpp
// Calculator.h — C++ class header accessible from JS
class Calculator {
public:
    double add(double a, double b) { return a + b; }
    double multiply(double a, double b) { return a * b; }
};

The Calculator class contains two arithmetic methods. We need to make it accessible from JS. To do this, a Host Object is created that wraps Calculator and exposes its methods through JSI.

cpp
// CalculatorHostObject.cpp — JSI wrapper implementation
class CalculatorHostObject : public jsi::HostObject {
private:
    Calculator calc;

public:
    jsi::Value get(jsi::Runtime& runtime,
        const jsi::PropNameID& name) override {
        auto propName = name.utf8(runtime);

        if (propName == "add") {
            return jsi::Function::createFromHostFunction(
                runtime, name, 2,
                [this](jsi::Runtime& runtime,
                    const jsi::Value& thisVal,
                    const jsi::Value* args,
                    size_t count) -> jsi::Value {
                    return jsi::Value(calc.add(
                        args[0].asNumber(),
                        args[1].asNumber()));
                });
        }
        return jsi::Value::undefined();
    }
};

In this code, the get method is called every time JS accesses a property of the object. If the property name is “add”, a C++ function is returned that takes two arguments from JS and calls calc.add(). The value is returned as jsi::Value — JSI automatically converts double to a JS number.

Calling from JavaScript

After registering the Host Object in the JS environment, the call looks like a regular JS function. All types are checked at the code generation stage, eliminating type mismatch errors during runtime.

js
// JavaScript — calling C++ calculator via JSI
import { Calculator } from 'react-native-calculator'

const result = Calculator.add(5, 3)
console.log(result) // 8 — synchronous, no delay

const product = Calculator.multiply(4, 2.5)
console.log(product) // 10 — immediate result

Note: the result is returned immediately, without Promise, without await, without callbacks. This is a synchronous call that was impossible in the Bridge architecture. For long-running operations (file reading, network request), asynchronous patterns should be used — JSI does not eliminate the need for background threads for heavy tasks.

In practice, most developers do not write JSI Host Objects manually — this work is done by Codegen, which generates C++ wrappers based on TypeScript specifications. However, understanding how JSI works under the hood is necessary for effective performance debugging and when creating complex native modules that require direct access to C++ libraries (Skia, FFmpeg, OpenCV).

Frequently Asked Questions

How is JSI different from Bridge in React Native?

Bridge works asynchronously through JSON serialization and a message queue — each call takes 3–10 ms for data conversion. JSI provides synchronous direct access to C++ objects without serialization, reducing latency to 0.1–0.5 ms. JSI also supports passing object references instead of copies.

Does JSI support all JavaScript engines?

Yes, JSI provides a unified C++ API that is implemented for Hermes (React Native default), JavaScriptCore (iOS), and V8 (Android). Developers do not need to write different code for different engines — Fabric and TurboModules work identically on all supported engines.

Can old native modules be used with JSI?

Yes, React Native provides a backward compatibility layer. Native modules written for Bridge continue to work in the new architecture. However, it is recommended to migrate them to TurboModules to gain the benefits of JSI — lazy loading and synchronous calls.

Does JSI require C++ knowledge?

For everyday development — no. TypeScript specifications of native modules are compiled into C++ bindings automatically through Codegen. C++ knowledge is only needed when creating custom C++ libraries or debugging JSI performance at the runtime level.

What problems does JSI solve?

JSI solves three key problems of Bridge: high latency due to JSON serialization, lack of synchronous calls, and inability to pass complex objects by reference. JSI also allows integrating C++ libraries directly, without Java or Objective-C intermediaries.

Summary

  • JSI (JavaScript Interface) — technology for direct synchronous access from JavaScript to C++ objects in React Native
  • Architecture JSI is based on Host Objects — C++ objects exported to JS as native JS objects
  • Performance of calls through JSI is 10–50x higher than through Bridge, due to the absence of serialization
  • Fabric and TurboModules — key components of the new React Native architecture, built on top of JSI
  • Synchronicity of JSI simplifies code logic but requires caution with long-running operations
  • C++ integration allows connecting any native libraries without platform wrappers
  • Use JSI for high-performance native modules and migrate existing ones from Bridge

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also