Performance
This guide covers performance optimization strategies for the Privacy Boost React Native SDK. Unlike the web SDK there’s no WASM to lazy-load — the heavy lifting runs in native iOS/Android binaries linked into the app. The costs to manage are SDK init, JS↔native bridge traffic, balance refresh frequency, and re-renders.SDK Lifecycle
One Instance Per JS Runtime
PrivacyBoost holds a JWT, identity keys, and an internal note cache. Construct it once in a module-level ref or a context provider — not inside a component that may unmount and remount.
Defer Init Until First Use
The first call into the native SDK pays one-time setup cost. If your app has flows that don’t touch the privacy pool (onboarding, splash, marketing), defer construction until the first gated screen — keep it off cold-start.Bridge Traffic
Every method on the SDK is a bridge call. The cost is small but not free — for tight loops or per-render fetches it adds up.Avoid Per-Render Fetches
Batch Where Possible
Don’t await Inside forEach
Balance Refresh
Centralize Through One Hook
Put refresh logic in a single hook so screens don’t each schedule their own polling:inflight deduplicates concurrent refreshes.
Refresh on Foreground, Not on a Timer
Tying refresh tosetInterval drains battery. Use AppState:
Re-Renders
Selector Subscriptions
If you’re using a global store (Zustand, Redux, Jotai), subscribe to the smallest slice:Stable Keys in FlatList
For transaction history, key by txHash so the list reuses rows:
Memoize Heavy Rows
If a row component does meaningful work (formatting amounts, deriving labels), wrap it inReact.memo:
Network
Parallelize Independent Reads
Page History — Don’t Fetch It All
Memory
Drop Off-Screen Pages
For long histories, store the visible window only and refetch on scroll-back instead of accumulating every page in state.FlatList’s removeClippedSubviews and windowSize reduce native view memory but won’t help your JS state.
Don’t Wrap Big Arrays in useState
Arrays of Transaction objects can be heavy. Prefer a normalized store keyed by txHash so component state holds only ids:
Operation Timing
Wrap SDK calls to observe timing during development:What the SDK Already Optimizes
Things you do not need to layer on top:- Note cache — the SDK caches unspent notes natively and only refetches new merkle tree leaves.
- Merkle tree pruning — proven nodes are kept; the rest are pruned.
- JWT reuse —
clearSession()keeps identity keys so the nextauthenticate()is fast. - Native execution — proofs run on the native side; the JS thread is not blocked while a shield is being generated.
Best Practices Summary
- One SDK instance per JS runtime — hold it in a module-level ref or a context provider.
- Defer SDK init until the first privacy-pool screen.
- Don’t fetch in render bodies — use
useEffectwith cleanup. - Refresh balances on
AppState === 'active'and after writes, not on a timer. - Deduplicate concurrent refreshes with an
inflightref. - Subscribe to the smallest slice of state your screen needs.
- Page transaction history; don’t fetch it all.
- Use
clearSession()overlogout()when re-auth is expected soon.