Lesson 19 of 26
The Bridge, JSI, and the Three Threads
The three RN threads (JS, native UI, and native modules), plus the historical bridge and the newer JSI mechanism that connects them.
React Native's biggest architectural idea isn't a component or an API — it's that your app is actually running on more than one thread at once, and those threads have to communicate with each other constantly. Understanding that model is the foundation for everything else in this part of the course: permissions, native modules, animations, and the New Architecture all come back to how JS and native code actually talk to each other.
Three threads, three jobs
A running React Native app involves (at least) three distinct threads, each with a different responsibility:
JS thread
Runs your React/JavaScript code — component functions, hooks, application logic, reconciliation. This is where your code actually executes.
Native UI thread
Also called the main thread. Actually lays out and renders real native views on screen, and handles touch input. This is what the user sees and touches, moment to moment.
Native modules thread(s)
Handles calls into native module code — camera access, filesystem, Bluetooth, and similar — often off the main thread specifically so a slow native call doesn't freeze the UI.
None of these threads run your code line-by-line together — they run independently, and coordinate by sending each other messages or, with newer mechanisms, by calling into each other more directly. Every performance concept in this course — dropped frames, native driver animations, why a busy JS thread makes scrolling stutter — is a consequence of this three-thread model, so it's worth being precise about it before moving on.
The bridge: how this used to work
For most of React Native's history, communication between the JS thread and the native side happened through what's called the bridge: an asynchronous, serialized message-passing mechanism. When JS needed something done natively — update a view's layout, call a native module — it didn't call directly into native code. Instead, a message describing that request was serialized (turned into a JSON-like representation), queued, and sent across to the native side, which processed a batch of queued messages, did the work, and sent results back the same way, again asynchronously.
This was a genuinely reasonable design: it kept JS and native code decoupled and meant a slow or crashing message wouldn't directly corrupt the other side's state. The cost was real too — every crossing between JS and native paid a serialization cost, and because everything was asynchronous and batched, there was no way for JS to synchronously ask native code for something and get an immediate answer back in the same tick.
JSI: a more direct connection
JSI, the JavaScript Interface, is the newer mechanism that changes this. Instead of every JS-to-native interaction being serialized into a message and queued, JSI lets a JavaScript object hold an actual reference to a native object (a "host object") and call methods on it far more directly — in some cases synchronously, without the message-passing and serialization overhead the old bridge required for every single crossing.
Conceptually, the shift looks like this:
Old bridge: JS --(serialize into message, queue, send)--> Native
JS <--(serialize result, queue, send)-- Native
JSI: JS --(direct reference, direct call)--> Native
JS <--(direct return value)-- Native
This is described here deliberately at a conceptual level rather than pinned to a specific version or exact current implementation detail — the platform is still actively evolving this mechanism, and the durable idea is "more direct communication, less required serialization," not any one version's precise internals.
Why this matters beyond trivia
JSI isn't just a faster version of the bridge for its own sake — it's the foundation the New Architecture is built on. The newer native-module system (TurboModules) and the newer rendering system (Fabric), both covered in a later lesson, are only possible because JSI gives JS and native code a way to interact that doesn't require every single call to pay the old bridge's serialization and batching cost. This lesson is deliberately scoped to the threading and communication model itself — what changes for you as a developer once those newer systems are actually in play is the subject of the New Architecture lesson later in this part.
What to remember
- A React Native app runs on (at least) three threads: the JS thread (your code), the native UI/main thread (renders real native views), and native module thread(s) (handle native calls, often off the main thread).
- The bridge was React Native's original JS-native communication mechanism: asynchronous, serialized, and batched — reliable, but with a real per-crossing cost.
- JSI (JavaScript Interface) is the newer mechanism, allowing more direct — sometimes synchronous — communication between JS and native, without the old bridge's serialization overhead.
- JSI is described here conceptually and deliberately not pinned to one exact current version's behavior, since the platform is still evolving it.
- JSI is the foundation the New Architecture (Fabric, TurboModules) is built on top of — covered in a later lesson.
Check yourself
4 questions · pass 3/4 to unlock Push Notifications, Conceptually
1.In the classic React Native architecture, what was 'the bridge'?
2.What does JSI (JavaScript Interface) enable that the old bridge didn't?
3.Which of these is the native UI thread's job, distinct from the JS thread's?
4.Why are native module calls often handled on their own thread(s), separate from the native UI thread?
4 left to answer