Documentation Index Fetch the complete documentation index at: https://mintlify.com/amark/gun/llms.txt
Use this file to discover all available pages before exploring further.
Rindexed Storage Adapter
Rindexed is GUN’s storage adapter for browser environments. It stores data in IndexedDB, the browser’s native database, with automatic fallback to in-memory storage when IndexedDB is unavailable.
Installation
Rindexed is included with GUN and automatically enabled in browser environments:
<!-- Include GUN in your HTML -->
< script src = "https://cdn.jsdelivr.net/npm/gun/gun.js" ></ script >
< script src = "https://cdn.jsdelivr.net/npm/gun/lib/rindexed.js" ></ script >
< script >
const gun = Gun ({
file: 'myapp' // IndexedDB database name
});
</ script >
With Module Bundlers
import Gun from 'gun' ;
import 'gun/lib/rindexed' ;
const gun = Gun ({
file: 'myapp-data'
});
With Node.js (for testing)
const Gun = require ( 'gun' );
require ( 'gun/lib/rindexed' );
const gun = Gun ({
file: 'test-db'
});
Configuration Options
Rindexed accepts the following configuration options:
const Store = require ( 'gun/lib/rindexed' );
const store = Store ({
file: 'myapp' , // IndexedDB database name
indexedDB: indexedDB // Optional: provide IndexedDB instance
});
Key Options
file (string)
Name of the IndexedDB database. This will appear in browser DevTools under Application > IndexedDB.
Default: 'radata'
const gun = Gun ({ file: 'myapp-v1' });
indexedDB (object)
Optional IndexedDB instance. Useful for testing or when using a custom IndexedDB implementation.
Default: window.indexedDB
const gun = Gun ({
file: 'myapp' ,
indexedDB: window . indexedDB || window . mozIndexedDB
});
How Rindexed Works
IndexedDB Storage
Rindexed creates an IndexedDB database with a single object store:
// Browser creates:
// Database: 'myapp'
// Object Store: 'myapp'
// Keys: encoded file names
// Values: JSON-encoded data
Storage Structure
Data is organized as key-value pairs:
// Example data stored in IndexedDB
{
// Key: "user%1Balice%1Bname"
// Value: "{\":\":\"Alice\",\">\":1234567890}"
// Key: "user%1Balice%1Bage"
// Value: "{\":\":30,\">\":1234567891}"
}
Automatic Fallback
If IndexedDB is unavailable (e.g., private browsing, file:// protocol), Rindexed automatically falls back to in-memory storage:
// Automatically detects and falls back
const gun = Gun ({ file: 'myapp' });
// Check if using IndexedDB or fallback
if ( gun . opt . store . d ) {
console . warn ( 'Using in-memory fallback (data will not persist)' );
} else {
console . log ( 'Using IndexedDB storage' );
}
Connection Reset (WebKit Bug Workaround)
Rindexed automatically closes and reopens the IndexedDB connection every 15 seconds to work around a WebKit bug:
// From rindexed.js:60
setInterval ( function () {
if ( db ) {
db . close ();
db = null ;
store . start ();
}
}, 1000 * 15 );
Storage Interface
Rindexed provides a standard storage interface:
const store = RindexedDB ({ file: 'myapp' });
// Write data
store . put ( 'key' , 'value' , function ( err , ok ) {
if ( err ) {
console . error ( 'Write failed:' , err );
} else {
console . log ( 'Write successful' );
}
});
// Read data
store . get ( 'key' , function ( err , value ) {
if ( err ) {
console . error ( 'Read failed:' , err );
} else {
console . log ( 'Value:' , value );
}
});
Browser Compatibility
Rindexed works in all modern browsers with IndexedDB support:
Browser Version IndexedDB Support Chrome 24+ ✅ Full support Firefox 16+ ✅ Full support Safari 10+ ✅ Full support Edge All versions ✅ Full support Opera 15+ ✅ Full support iOS Safari 10+ ✅ Full support Android 4.4+ ✅ Full support
Private Browsing Mode
In private/incognito mode, some browsers restrict IndexedDB:
Chrome/Edge : IndexedDB works normally
Firefox : IndexedDB works normally
Safari : IndexedDB may be disabled (fallback to memory)
Rindexed automatically detects this and uses in-memory storage.
Storage Quota
Browsers limit how much data you can store in IndexedDB:
Checking Available Quota
if ( navigator . storage && navigator . storage . estimate ) {
navigator . storage . estimate (). then ( function ( quota ) {
console . log ( 'Used:' , quota . usage , 'bytes' );
console . log ( 'Total:' , quota . quota , 'bytes' );
console . log ( 'Percentage:' , ( quota . usage / quota . quota * 100 ). toFixed ( 2 ) + '%' );
console . log ( 'Remaining:' , quota . quota - quota . usage , 'bytes' );
});
}
Requesting Persistent Storage
For critical applications, request persistent storage to prevent eviction:
if ( navigator . storage && navigator . storage . persist ) {
navigator . storage . persist (). then ( function ( persistent ) {
if ( persistent ) {
console . log ( 'Storage will not be cleared except by explicit user action' );
} else {
console . log ( 'Storage may be cleared under storage pressure' );
}
});
}
Typical Quota Limits
Browser Quota Type Limit Chrome Temporary Up to 60% of total disk Firefox Temporary Up to 50% of free disk Safari Temporary ~1 GB Edge Temporary Up to 60% of total disk
Data Persistence
When Data Persists
IndexedDB data persists:
✅ Across browser sessions
✅ After browser restart
✅ After system reboot
✅ During offline use
When Data May Be Cleared
Browsers may clear IndexedDB data:
⚠️ When disk space is low (temporary storage)
⚠️ After extended periods of inactivity
⚠️ When user clears browser data
⚠️ In private browsing mode (after session)
Working with GUN
Basic Setup
import Gun from 'gun' ;
import 'gun/lib/rindexed' ;
const gun = Gun ({
file: 'myapp-data' ,
peers: [ 'https://gun-server.example.com/gun' ]
});
// Store data (automatically saved to IndexedDB)
gun . get ( 'settings' ). put ({
theme: 'dark' ,
notifications: true
});
// Read data (loaded from IndexedDB)
gun . get ( 'settings' ). once ( function ( data ) {
console . log ( 'Settings:' , data );
});
Offline-First Applications
const gun = Gun ({
file: 'offline-app' ,
localStorage: false , // Disable localStorage
radisk: false // Browser doesn't use radisk
});
// Write data while offline
gun . get ( 'todos' ). get ( 'task1' ). put ({
title: 'Buy milk' ,
done: false ,
created: Date . now ()
});
// Data is stored locally in IndexedDB
// When back online, GUN syncs with peers
Progressive Web Apps (PWA)
// service-worker.js
self . addEventListener ( 'install' , function ( event ) {
// GUN data is already in IndexedDB
// No additional caching needed
});
// app.js
import Gun from 'gun' ;
import 'gun/lib/rindexed' ;
const gun = Gun ({
file: 'pwa-app' ,
peers: [ 'https://api.example.com/gun' ]
});
// Request persistent storage for PWA
if ( navigator . storage && navigator . storage . persist ) {
navigator . storage . persist ();
}
Batching Writes
Rindexed batches operations automatically, but you can optimize further:
// Bad: Many individual writes
for ( let i = 0 ; i < 1000 ; i ++ ) {
gun . get ( 'items' ). get ( i ). put ({ value: i });
}
// Better: Batch related data
const items = {};
for ( let i = 0 ; i < 1000 ; i ++ ) {
items [ i ] = { value: i };
}
gun . get ( 'items' ). put ( items );
Limiting Data Size
Keep individual values small for better performance:
// Bad: Store large objects
gun . get ( 'user/alice' ). put ({
name: 'Alice' ,
posts: [ /* 1000 posts */ ],
comments: [ /* 5000 comments */ ]
});
// Better: Separate concerns
gun . get ( 'user/alice' ). put ({ name: 'Alice' });
gun . get ( 'user/alice/posts' ). put ( /* posts */ );
gun . get ( 'user/alice/comments' ). put ( /* comments */ );
const store = gun . opt . store ;
// Track operation timing
let startTime = performance . now ();
store . put ( 'key' , 'value' , function ( err , ok ) {
const duration = performance . now () - startTime ;
console . log ( 'Write took' , duration , 'ms' );
});
Debugging
Open browser DevTools (F12)
Go to Application tab
Expand IndexedDB in sidebar
Find your database (e.g., “myapp”)
Expand object stores to view data
Reading Raw Data
// Open IndexedDB directly
const request = indexedDB . open ( 'myapp' , 1 );
request . onsuccess = function ( event ) {
const db = event . target . result ;
const tx = db . transaction ([ 'myapp' ], 'readonly' );
const store = tx . objectStore ( 'myapp' );
const allKeys = store . getAllKeys ();
allKeys . onsuccess = function () {
console . log ( 'All keys:' , allKeys . result );
};
};
Clearing Data
// Clear all data for debugging
const request = indexedDB . deleteDatabase ( 'myapp' );
request . onsuccess = function () {
console . log ( 'Database deleted' );
location . reload ();
};
request . onerror = function () {
console . error ( 'Failed to delete database' );
};
Troubleshooting
”Warning: No indexedDB exists to persist data to!”
This warning appears when IndexedDB is unavailable. Common causes:
File protocol : Load your page via http:// or https://, not file://
Private browsing : Some browsers disable IndexedDB in private mode
Browser too old : Update to a modern browser
// Check if IndexedDB is available
if ( ! window . indexedDB ) {
console . warn ( 'IndexedDB not supported' );
}
”QuotaExceededError”
You’ve exceeded the storage quota:
store . put ( 'key' , 'value' , function ( err ) {
if ( err && err . name === 'QuotaExceededError' ) {
console . error ( 'Storage quota exceeded' );
// Clear old data or request more storage
}
});
Connection Errors
If you see transaction errors:
// Ensure you're not keeping transactions open
store . get ( 'key' , function ( err , value ) {
if ( err ) {
console . error ( 'Transaction error:' , err );
}
// Don't perform async operations before callback
});
Best Practices
Set a meaningful database name : Use file option to name your database
Request persistent storage : For important apps, request persistence
Monitor quota usage : Check available storage regularly
Handle offline gracefully : IndexedDB works offline
Clear old data : Implement data retention policies
Test in private mode : Ensure fallback works
Use version numbers : Include version in database name for migrations
Next Steps
RADisk Adapter File system storage for Node.js
S3 Adapter Cloud storage with Amazon S3
Custom Adapters Build your own storage adapter
Offline Apps Build offline-first applications