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.
RADisk Storage Adapter
RADisk is GUN’s default storage adapter for Node.js environments. It stores data as files on the file system using an efficient Radix tree structure for fast queries and range lookups.
Installation
RADisk is included with GUN and automatically enabled in Node.js environments:
const Gun = require ( 'gun' );
require ( 'gun/lib/radisk' ); // Explicitly load RADisk
const gun = Gun ({
file: 'radata' // Directory for data files
});
Configuration Options
RADisk accepts the following configuration options:
const Radisk = require ( 'gun/lib/radisk' );
const rad = Radisk ({
// Required: storage interface
store: {
get : function ( file , callback ) { },
put : function ( file , data , callback ) { },
list : function ( callback ) { } // optional
},
// Optional configuration
file: 'radata' , // Base directory name
log: console . log , // Logging function
max: 300000000 * 0.3 , // Max file size (90MB default)
until: 250 , // Batch delay in milliseconds
wait: 250 , // Alias for 'until'
batch: 10000 , // Max items per batch
chunk: 1024 * 1024 , // Chunk size (1MB default)
jsonify: true , // Use JSON format (default)
// Comparison function for updates
compare : function ( oldData , newData , key , file ) {
// Return newData to save, undefined to skip
return newData ;
}
});
Key Options
file (string)
Base directory or file name for storing data.
Default: 'radata'
const gun = Gun ({ file: 'myapp-data' });
until / wait (number)
Time in milliseconds to wait before writing batched data to disk. This allows multiple writes to be grouped together.
Default: 250
const gun = Gun ({
file: 'radata' ,
until: 500 // Wait 500ms before writing
});
batch (number)
Maximum number of write operations to batch before forcing a disk write.
Default: 10000
chunk (number)
Maximum size (in bytes) for a single data file before it’s automatically split.
Default: 1048576 (1MB)
const gun = Gun ({
file: 'radata' ,
chunk: 1024 * 1024 * 10 // 10MB chunks
});
max (number)
Maximum size for individual data values.
Default: 90000000 (90MB)
jsonify (boolean)
Whether to use JSON format for storage. When true, data is stored as JSON objects. When false, uses the legacy RAD encoding format.
Default: true
How RADisk Works
File Organization
RADisk creates a directory structure to store your data:
radata/
├── %1C # Directory index file
├── %21 # Data file for keys starting with '!'
├── user%1Balice # Data file for 'user/alice' and similar keys
├── user%1Bbob # Data file for 'user/bob' and similar keys
└── ... # More data files as needed
File names are URL-encoded to handle special characters:
%1C - Character code 28 (directory file)
%1B - The escape character separating soul and key
%21 - Exclamation mark (’!’)
Radix Tree Storage
RADisk uses a Radix tree to efficiently organize keys:
// Example: Storing user data
gun . get ( 'user/alice' ). put ({ name: 'Alice' , age: 30 });
gun . get ( 'user/bob' ). put ({ name: 'Bob' , age: 25 });
// Internally stored in Radix tree:
{
"user" : {
"/alice/name" : { ":" : "Alice" , ">" : 1234567890 },
"/alice/age" : { ":" : 30 , ">" : 1234567891 },
"/bob/name" : { ":" : "Bob" , ">" : 1234567892 },
"/bob/age" : { ":" : 25 , ">" : 1234567893 }
}
}
Automatic File Splitting
When a data file exceeds the chunk size, RADisk automatically splits it:
Creates a new file for the second half of the keys
Updates the original file to contain only the first half
Updates the directory index to track both files
This keeps file sizes manageable and improves read performance.
Write Batching
RADisk batches writes to improve performance:
// These three writes are batched together
gun . get ( 'user/alice' ). put ({ name: 'Alice' });
gun . get ( 'user/bob' ). put ({ name: 'Bob' });
gun . get ( 'user/carol' ). put ({ name: 'Carol' });
// After 250ms (default), all three writes go to disk in one operation
Benefits:
Reduces disk I/O operations
Improves write performance
Reduces risk of corruption from partial writes
Storage Interface
RADisk requires a storage interface with get and put methods:
const fs = require ( 'fs' );
const path = require ( 'path' );
const store = {
// Read a file
get : function ( file , callback ) {
fs . readFile ( path . join ( 'radata' , file ), 'utf8' , function ( err , data ) {
if ( err && err . code === 'ENOENT' ) {
// File doesn't exist - this is not an error
return callback ( null , undefined );
}
callback ( err , data );
});
},
// Write a file
put : function ( file , data , callback ) {
fs . writeFile ( path . join ( 'radata' , file ), data , function ( err ) {
callback ( err , err ? null : 1 );
});
},
// List all files (optional, but recommended)
list : function ( callback ) {
fs . readdir ( 'radata' , function ( err , files ) {
if ( err ) return callback ();
files . forEach ( callback );
callback (); // Signal end of list
});
}
};
const rad = Radisk ({ file: 'radata' , store: store });
Read and Write Operations
Writing Data
// Write a key-value pair
rad ( 'user/alice' , { ':' : 'Alice' , '>' : Date . now () }, function ( err , ok ) {
if ( err ) {
console . error ( 'Write failed:' , err );
} else {
console . log ( 'Write successful' );
}
});
Reading Data
// Read by exact key
rad ( 'user/alice' , function ( err , data ) {
if ( err ) {
console . error ( 'Read failed:' , err );
} else {
console . log ( 'Data:' , data );
// { ':': 'Alice', '>': 1234567890 }
}
});
// Range query
rad ( 'user/' , function ( err , data ) {
console . log ( 'All user keys:' , data );
}, {
start: 'user/a' ,
end: 'user/z'
});
High-Throughput Scenarios
For applications with high write volume:
const gun = Gun ({
file: 'radata' ,
until: 100 , // Write more frequently
batch: 50000 , // Allow larger batches
chunk: 1024 * 1024 * 5 // 5MB chunks
});
Large Data Sets
For applications storing large amounts of data:
const gun = Gun ({
file: 'radata' ,
chunk: 1024 * 1024 * 10 , // 10MB chunks
max: 500000000 * 0.3 // Allow larger individual files
});
Low Latency Requirements
For applications requiring fast writes:
const gun = Gun ({
file: 'radata' ,
until: 50 , // Write after 50ms
batch: 1000 // Smaller batches
});
With jsonify: true, data is stored as JSON:
{
"user/alice/name" : {
":" : "Alice" ,
">" : 1234567890
},
"user/alice/age" : {
":" : 30 ,
">" : 1234567891
}
}
With jsonify: false, data uses the RAD encoding:
!#"user"!#"alice"!#"name":"Alice"
!#"user"!#"alice"!#"age":+30!
The RAD format uses special encoding:
! - Field separator (ASCII 31)
# - Prefix length indicator
" - String value
+ - Number value
: - Value separator
File System Considerations
Directory Structure
Ensure the storage directory exists and has proper permissions:
const fs = require ( 'fs' );
// Create directory if it doesn't exist
if ( ! fs . existsSync ( 'radata' )) {
fs . mkdirSync ( 'radata' , { recursive: true });
}
Backup and Recovery
To backup RADisk data:
# Simple backup
tar -czf backup.tar.gz radata/
# Incremental backup with rsync
rsync -av radata/ backup/radata/
To restore:
# Extract backup
tar -xzf backup.tar.gz
Cleaning Up
RADisk automatically manages file lifecycle, but you can manually clean up if needed:
const fs = require ( 'fs' );
const path = require ( 'path' );
// Remove all data files
fs . readdir ( 'radata' , ( err , files ) => {
if ( err ) return console . error ( err );
files . forEach ( file => {
fs . unlink ( path . join ( 'radata' , file ), err => {
if ( err ) console . error ( err );
});
});
});
Troubleshooting
Error: “Radisk needs opt.store interface”
You must provide a storage interface:
const Radisk = require ( 'gun/lib/radisk' );
const rad = Radisk ({
store: {
get : function ( file , cb ) { /* ... */ },
put : function ( file , data , cb ) { /* ... */ }
}
});
Error: “Data too big!”
Increase the max option:
const gun = Gun ({
file: 'radata' ,
max: 1000000000 * 0.3 // Allow larger values
});
Corrupt File Recovery
RADisk automatically detects and removes corrupt files:
// RADisk will log corrupt files and attempt recovery
// Check console output for:
// "File 'filename' does not have root radix!"
Best Practices
Use appropriate chunk sizes : Smaller chunks for many small writes, larger chunks for fewer large writes
Enable batching : Keep until at 250ms or higher for better performance
Backup regularly : Use file system snapshots or regular backups
Monitor disk space : RADisk can grow based on your data
Use JSON format : The default JSON format is more debuggable than RAD format
Next Steps
Rindexed Adapter Browser storage with IndexedDB
S3 Adapter Cloud storage with Amazon S3
Custom Adapters Build your own storage adapter
Performance Optimize GUN performance