npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-turbo-db

v1.5.0

Published

react-native-turbo-db is a high-performance JSI database and AsyncStorage alternative for React Native, featuring encrypted storage, WAL persistence, B+tree indexing and offline-first local database support.

Downloads

4

Readme

react-native-turbo-db is a high-performance JSI database and AsyncStorage alternative for React Native, featuring encrypted storage, WAL persistence, B+tree indexing, and offline-first local database support.

⚡ What's New in v1.5.0 (Security Release)

TurboDB v1.5.0 is a dedicated hardening release focused on encryption correctness and hardware-backed security:

  • 🔐 XChaCha20-Poly1305 Encryption — All data at rest is encrypted via libsodium. The SecureCryptoContext class now correctly wires through every read/write path in the C++ engine.
  • 🔑 Encryption Key RotationrotateEncryptionKeyAsync(newKey) re-encrypts all records in a single atomic pass without downtime.
  • 🛡️ Hardware Secure EnclavesetSecureItemAsync / getSecureItemAsync now use the device Keystore (Android) and Secure Enclave (iOS) for master-key storage.
  • 🐛 Critical C++ Fix — Resolved incorrect SodiumCryptoContext instantiation that silently disabled encryption in the DBEngine constructor.
  • Android Build Stabilised — Removed stale calculate_crc32 dependency; repair logic now delegates cleanly to PersistentBPlusTree::repair().

[!NOTE] Built on v1.4.0 Reactive Sync (Live Queries, Real Sync Engine, Correct Compaction)


🚀 Quick Start

Installation

npm install react-native-turbo-db
cd ios && pod install

Setup

Android

Ensure newArchEnabled=true in your android/gradle.properties:

newArchEnabled=true

iOS

No additional configuration required. The pod installs automatically.


📖 Usage

Basic Initialization

[!IMPORTANT] Always use absolute paths from TurboDB.getDocumentsDirectory().

import { TurboDB } from 'react-native-turbo-db';

const initDB = async () => {
  // ⚠️ Important for New Architecture (Bridgeless / Fabric):
  // A short delay before the first JSI call ensures native modules are fully wired up
  await new Promise((r) => setTimeout(r, 100));

  const docsDir = TurboDB.getDocumentsDirectory();
  const dbPath = `${docsDir}/myapp.db`;

  // Initialize with async factory (recommended)
  const db = await TurboDB.create(dbPath, 20 * 1024 * 1024, {
    syncEnabled: true,
  });
  return db;
};

Synchronous Operations (Fast Path)

// Write (instant)
db.set('user:1', { name: 'Alice', role: 'admin' });

// Read (instant)
const user = db.get('user:1');

// Batch write
db.setMulti({
  key1: 'value1',
  key2: { data: 'object' },
});

// Check existence & Delete
if (db.has('user:1')) {
  db.remove('user:1');
}

Asynchronous Operations (Background Thread)

// For large data, use async to avoid blocking UI
await db.setAsync('largeData', hugePayload);
const data = await db.getAsync('largeData');

// Batch async write (10x faster with WAL batching)
await db.setMultiAsync(largeBatchObject);

⚡ Live Queries & Reactive Sync (v1.4.0)

TurboDB now supports native real-time subscriptions. The UI will instantly update even if writes happen on a C++ background thread!

import { useEffect, useState } from 'react';

function ChatApp({ db }) {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    // Subscribe to all keys starting with 'msg:'
    const unsubscribe = db.watchPrefix('msg:', (results) => {
      setMessages(results.map(r => r.value));
    });
    return () => unsubscribe();
  }, [db]);

  // Calling setAsync here triggers the watchPrefix callback automatically!
  const send = async (text) => db.setAsync(`msg:${Date.now()}`, { text });
}

Advanced Queries

// Range query & Prefix search
const results = db.rangeQuery('user_a', 'user_z');
const items = db.getByPrefix('user_');

// Metadata & Cleanup
const allKeys = db.getAllKeys();
await db.deleteAllAsync();

Initialization

| Method | Description | | :------------------------------------ | :--------------------------------------------------- | | TurboDB.create(path, size, options) | Async factory. Returns Promise<TurboDB>. | | TurboDB.getDocumentsDirectory() | Returns absolute path for storage. | | TurboDB.install() | Installs native JSI bindings (called automatically). |

Synchronous (Blocking)

| Method | Description | | :----------------------- | :---------------------------------------------- | | get(key) | Returns parsed object/primitive or undefined. | | set(key, val) | Writes to storage. Returns boolean. | | has(key) | Checks if key exists. | | remove(key) | Deletes a record. | | setMulti(obj) | Atomic batch insert. | | getMultiple(keys) | Batch retrieval. | | rangeQuery(start, end) | Lexicographical range fetch. | | getByPrefix(prefix) | Fetch all keys starting with prefix. | | deleteAll() | Synchronous database wipe. | | getAllKeys() | Returns all keys in storage. |

Asynchronous (Worker Thread)

| Method | Description | | :---------------------------- | :---------------------------------------------------------- | | getAsync(key) | Background read. Returns Promise. | | setAsync(key, val) | Background write. Returns Promise<boolean>. | | setMultiAsync(obj) | 10x Faster WAL Batching. Atomic background batch write. | | removeAsync(key) | Background delete. | | deleteAllAsync() | Fast-path wipe for large datasets. | | rangeQueryAsync(start, end) | Background range fetch. | | getAllKeysAsync() | Background get all keys. |

Extended API (v1.4.0 / v1.5.0)

| Method | Description | | :----------------------------------------- | :----------------------------------------------------------------------- | | watchKey(key, cb) | Reactive key watcher — fires immediately, returns unsubscribe | | watchPrefix(prefix, cb, opts?) | Reactive prefix query with optional debounce | | watchQuery(fn, cb, opts?) | Reactive arbitrary async query with debounce | | compactAsync() | Native compaction with fragmentation guard (>30%) | | setWithTTLAsync(key, val, ttlMs) | Native TTL — durable expiry via C++ sidecar key | | cleanupExpiredAsync() | Native sweep of all expired TTL keys. Returns count. | | getByPrefixAsync(prefix) | Native B+Tree prefix traversal | | regexSearchAsync(pattern) | Regex key filter using std::regex | | exportAsync() | Full DB snapshot as JSON (native traversal) | | importAsync(data) | Bulk insert from JSON. Returns record count. | | setBlobAsync(key, base64) | Store raw binary data >1MB | | getBlobAsync(key) | Retrieve raw binary as base64 | | compareAndSet(key, expected, next) | Atomic compare-and-set | | merge(key, partial) | Shallow-merge into existing object | | setSecureItemAsync(key, val) | v1.5.0 Hardware Secure Enclave / Android Keystore storage | | getSecureItemAsync(key) | v1.5.0 Retrieve from Secure Enclave / Android Keystore | | rotateEncryptionKeyAsync(newKey) | v1.5.0 Atomic key rotation — re-encrypts all records in one pass | | for await (const key of db.streamKeys()) | Async key streaming for large datasets |

Internal Architecture

graph LR
    JS[JavaScript Layer] -- JSI (Zero Bridge) --> CPP[C++ TurboDB Engine]
    CPP -- mmap --> File[(myapp.db)]
    CPP -- atomic --> WAL[Write-Ahead Log]
    WAL -- checkpoint --> File
    CPP -- cache --> LRU[JSI LRU Cache]

TurboDB utilizes a custom B+Tree Index on top of a Memory-Mapped (mmap) file, secured by a Write-Ahead Log (WAL) for ACID compliance. JSI allows direct communication between C++ and JavaScript, eliminating bridge overhead.

SyncManager (Offline-First)

Built-in synchronization for remote backends:

import { SyncManager } from 'react-native-turbo-db';

const syncManager = new SyncManager(
  db,
  {
    pullChanges: async (lastClock) =>
      fetch(`/api/sync?since=${lastClock}`).then((r) => r.json()),
    pushChanges: async (changes) =>
      fetch('/api/sync', {
        method: 'POST',
        body: JSON.stringify(changes),
      }).then((r) => r.json()),
  },
  { autoSync: true }
);

await syncManager.start();

⚡ Benchmarks

TurboDB is engineered for extreme performance. Below are representative results comparing operations across popular storage solutions (measured on iPhone 15 Pro, 10,000 iterations).

| Operation | AsyncStorage | MMKV | TurboDB | | :-------------------------- | :----------: | :----: | :-------------: | | Write (Small Object) | ~850ms | ~45ms | ~12ms | | Read (Small Object) | ~420ms | ~35ms | ~8ms | | Batch Write (100 items) | ~1200ms | ~150ms | ~15ms (WAL) | | Range Query | ❌ | ❌ | ✅ <5ms |

[!NOTE] Methodology: Benchmarks performed on iPhone 15 Pro (iOS 17.4) and Pixel 8 (Android 14) using react-native-performance. Each test represents an average of 10,000 iterations. See our benchmark suite for full details.

[!TIP] TurboDB is 10x faster than AsyncStorage and significantly outpaces MMKV in batch operations thanks to its Write-Ahead Log (WAL) architecture.


🆚 Why TurboDB? (Comparison)

| Feature | TurboDB | AsyncStorage | MMKV | SQLite (Bridge) | | :--------------- | :-----------------: | :----------: | :--------: | :-------------: | | Architecture | JSI C++ | Async Bridge | JSI C++ | Async Bridge | | Best For | Complex Objects | Simple Prefs | Primitives | Relational Data | | Encryption | ✅ XChaCha20 | ❌ | ❌ | ❌ | | Transactions | ✅ (WAL) | ❌ | ❌ | ✅ | | Indexing | ✅ B+Tree | ❌ | ❌ | ✅ | | Offline Sync | ✅ Built-in | ❌ | ❌ | ❌ |


🌐 Platform Support

| Platform | New Architecture | Old Architecture | Min Version | | :------------ | :--------------: | :--------------: | :------------ | | iOS | ✅ Full | ✅ Fallback | iOS 15.1+ | | Android | ✅ Full | ✅ Fallback | SDK 24+ (7.0) | | Web (SSR) | ✅ Full | ✅ Full | Chrome 90+ |


🚀 Examples


🔧 Troubleshooting

"Failed to initialize storage" Error

[!CAUTION] Ensure you are using an absolute path.

  1. Use absolute path: Always use TurboDB.getDocumentsDirectory() + filename.
  2. Add delay: If native modules aren't ready, add a 1-second delay before TurboDB.create().
  3. Clean State: Call await db.deleteAllAsync() if you need a fresh start after creation.

Native Module Not Found

  1. Run cd ios && pod install.
  2. Clean rebuild: cd android && ./gradlew clean.
  3. Verify newArchEnabled=true in gradle.properties.

JSI Runtime Errors

[!WARNING] Do not use the constructor directly (new TurboDB()).

Always use the async factory:

const db = await TurboDB.create(path, size);

📄 License

MIT © Ganesh Jayaprakash