Prewarming
Start a runtime before its UI is visible to remove cold-start latency.
Prewarming creates and starts a named secondary runtime before a surface needs it. The runtime is ready when the first surface mounts, so the user sees no cold-start delay.
import { ThreadedRuntime } from '@react-native-runtimes/core';
await ThreadedRuntime.prewarm('conversation-release-room-runtime');preload is an alias of prewarm:
await ThreadedRuntime.preload('conversation-release-room-runtime');ThreadedScreen preloads its runtime by default, but that preload runs from a
React effect — meaning the runtime starts at roughly the same time the screen
mounts. For low-latency navigation, prewarm earlier, such as while a
picker or inbox is visible:
const runtimeNames = conversations.map(
conversation => `conversation-${conversation.id}-runtime`,
);
useEffect(() => {
for (const runtimeName of runtimeNames) {
void ThreadedRuntime.prewarm(runtimeName);
}
}, [runtimeNames]);On tap, prewarm the selected runtime again before switching screens. The call is cheap when the runtime already exists, so this is safe to do liberally:
function openConversation(conversationId: string) {
void ThreadedRuntime.prewarm(`conversation-${conversationId}-runtime`);
setSelectedConversationId(conversationId);
}Best-effort + cheap when warm
Calling prewarm on an already-started runtime is essentially free. Treat
it as a hint, not an expensive imperative call.
Native prewarm
Prewarm from native code for runtimes that should exist before any JS runs —
typically your background runtime or a chat inbox.
ThreadedRuntime.prewarmRuntime(
applicationContext,
"conversation-release-room-runtime",
)ThreadedRuntime.prewarmRuntime("conversation-release-room-runtime")#include <nativecompose/threadedruntime/ThreadedRuntimeDispatcher.h>
nativecompose::threadedruntime::prewarmRuntime(
"conversation-release-room-runtime"
);Releasing runtimes
Destroy a named runtime when it no longer owns useful work:
await ThreadedRuntime.destroy('conversation-release-room-runtime');For route components, set destroyOnUnmount when the screen should release
the runtime immediately:
<ThreadedScreen
component={ConversationScreen}
destroyOnUnmount
props={{ conversationId }}
runtimeName={`conversation-${conversationId}-runtime`}
/>Don't destroy app-lifetime runtimes
A background runtime that owns sync, caching, or queues should never be
destroyed during normal app use. Only call destroy for runtimes you're
sure no one else needs.
Strategy cheat sheet
| Situation | Recommendation |
|---|---|
| User likely to open screen X within 5 seconds | Prewarm X's runtime from a parent screen's effect |
| App-lifetime background work | Prewarm from native at startup |
| Per-conversation chat | Prewarm a small N (e.g. 3–5 visible inbox items) ahead, prewarm the selected one on tap |
| Rarely-used heavy feature | Don't prewarm — let the surface start the runtime on demand |