node-persist vs levelup vs localforage vs lowdb vs nedb vs pouchdb
JavaScript Data Storage Libraries
node-persistleveluplocalforagelowdbnedbpouchdbSimilar Packages:

JavaScript Data Storage Libraries

These libraries provide various solutions for data storage in JavaScript applications, catering to different needs such as local storage, persistence, and synchronization. They enable developers to manage data efficiently, whether in a server-side Node.js environment or client-side web applications. Each library has unique features and use cases, making it essential to choose the right one based on the specific requirements of your project.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
node-persist211,77972840.1 kB17a year agoMIT
levelup04,076-05 years agoMIT
localforage025,782-2495 years agoApache-2.0
lowdb022,53822.9 kB152 years agoMIT
nedb013,549-20910 years agoSEE LICENSE IN LICENSE
pouchdb017,5645.53 MB1732 years agoApache-2.0

Feature Comparison: node-persist vs levelup vs localforage vs lowdb vs nedb vs pouchdb

Storage Type

  • node-persist:

    Node-Persist is a key-value store that saves data to the file system, providing a simple way to persist data in Node.js applications. It is ideal for applications that require basic data storage without complex features.

  • levelup:

    LevelUP is a wrapper around LevelDB, providing a key-value store that is fast and efficient for large datasets. It is designed for server-side applications, allowing for complex data structures and high performance.

  • localforage:

    LocalForage abstracts different storage mechanisms like IndexedDB, WebSQL, and localStorage, allowing developers to use a simple API for asynchronous storage. It is primarily used for client-side applications needing offline capabilities.

  • lowdb:

    LowDB is a simple JSON database that stores data in a JSON file, making it easy to read and write. It is suitable for small projects and prototyping, where a lightweight solution is needed without complex setup.

  • nedb:

    NeDB is an embedded database that provides a MongoDB-like API for Node.js applications. It stores data in a file and supports indexing, making it suitable for applications that need a lightweight database with querying capabilities.

  • pouchdb:

    PouchDB is a NoSQL database that can sync with CouchDB, allowing for offline data storage and synchronization across devices. It is designed for web and mobile applications that require robust data handling and offline capabilities.

Ease of Use

  • node-persist:

    Node-Persist has a simple API for storing and retrieving key-value pairs, making it easy for developers to implement persistent storage in their applications.

  • levelup:

    LevelUP has a straightforward API that allows developers to perform CRUD operations easily. However, it requires some understanding of LevelDB concepts to utilize its full potential effectively.

  • localforage:

    LocalForage offers a simple and intuitive API that makes it easy for developers to store and retrieve data asynchronously, making it a great choice for web applications.

  • lowdb:

    LowDB is extremely easy to set up and use, with a minimalistic API that allows developers to read and write data in JSON format without much overhead.

  • nedb:

    NeDB provides a familiar MongoDB-like API, making it easy for developers who are already accustomed to MongoDB to use it without a steep learning curve.

  • pouchdb:

    PouchDB has a user-friendly API that simplifies data synchronization and offline storage, making it accessible for developers to implement complex features without much hassle.

Performance

  • node-persist:

    Node-Persist is suitable for small-scale applications, but performance may degrade with larger datasets due to file system I/O operations.

  • levelup:

    LevelUP is optimized for performance, especially with large datasets, as it leverages LevelDB's efficient storage and retrieval mechanisms, making it suitable for high-performance applications.

  • localforage:

    LocalForage provides good performance for client-side storage, but its speed can vary depending on the underlying storage mechanism used by the browser.

  • lowdb:

    LowDB is not designed for high-performance applications, as it reads and writes data to a JSON file, which can become a bottleneck with larger datasets.

  • nedb:

    NeDB offers decent performance for small to medium-sized datasets, but it may struggle with very large datasets due to its file-based storage approach.

  • pouchdb:

    PouchDB is designed for performance and can handle large datasets efficiently, especially with its ability to sync data with CouchDB.

Data Synchronization

  • node-persist:

    Node-Persist does not provide synchronization capabilities, focusing instead on simple key-value storage.

  • levelup:

    LevelUP does not provide built-in data synchronization features, as it is primarily focused on local storage and retrieval.

  • localforage:

    LocalForage does not support data synchronization out of the box, but it can be used in conjunction with other libraries to achieve this functionality.

  • lowdb:

    LowDB does not offer data synchronization features, as it is intended for simple, local data storage without complex requirements.

  • nedb:

    NeDB does not natively support data synchronization, but it can be used in applications where data consistency is managed manually.

  • pouchdb:

    PouchDB excels in data synchronization, allowing seamless syncing with CouchDB and other PouchDB instances, making it ideal for applications that require offline capabilities and data consistency across devices.

Use Cases

  • node-persist:

    Node-Persist is great for applications that need simple key-value storage, such as caching or storing user preferences in Node.js applications.

  • levelup:

    LevelUP is best suited for applications that require a fast and efficient key-value store, such as caching, session storage, or managing large datasets in Node.js environments.

  • localforage:

    LocalForage is ideal for web applications that need to store user data offline, such as progressive web apps (PWAs) that require persistent storage across sessions.

  • lowdb:

    LowDB is perfect for small projects, prototypes, or applications that need a simple, file-based database without the overhead of a full database system.

  • nedb:

    NeDB is suitable for desktop applications or small server-side applications that require a lightweight database with a familiar API for MongoDB users.

  • pouchdb:

    PouchDB is best for mobile and web applications that require robust offline capabilities and data synchronization across devices, making it ideal for collaborative applications.

How to Choose: node-persist vs levelup vs localforage vs lowdb vs nedb vs pouchdb

  • node-persist:

    Choose Node-Persist if you need a simple and persistent key-value store for Node.js applications. It is easy to use and provides a straightforward way to store data on the file system, making it suitable for small-scale applications or caching.

  • levelup:

    Choose LevelUP if you need a simple and flexible way to work with LevelDB, especially for applications that require a fast key-value store with a focus on performance and scalability. It's ideal for Node.js applications that need to handle large amounts of data efficiently.

  • localforage:

    Select LocalForage if you are looking for a library that provides a simple API for asynchronous storage, supporting multiple backends like IndexedDB, WebSQL, and localStorage. It's perfect for web applications that require offline capabilities and a consistent API across different browsers.

  • lowdb:

    Opt for LowDB if you need a lightweight JSON database for small projects or prototyping. It is easy to set up and use, making it suitable for applications that require simple data storage without the overhead of a full database system.

  • nedb:

    Use NeDB if you want a lightweight, embedded database for Node.js applications that resembles MongoDB's API. It is suitable for applications that require a simple, file-based database with indexing and querying capabilities without the need for a full-fledged database server.

  • pouchdb:

    Select PouchDB if you need a powerful database that can sync with CouchDB and work offline. It is ideal for applications that require data synchronization across devices and offline capabilities, making it suitable for mobile and web applications.

README for node-persist

node-persist - localStorage on the server

Super-easy asynchronous persistent data structures in Node.js, modeled after HTML5 localStorage

Node-persist doesn't use a database. Instead, JSON documents are stored in the file system for persistence. Because there is no network overhead, node-persist is just about as fast as a database can get. Node-persist uses the HTML5 localStorage API, so it's easy to learn.

This is still a work in progress. Send pull requests please.

Note

  • This is not designed for large amounts of data, you can do way more than the 5MB limit imposed by the browsers but don't stretch it, in some cases you might need to load the whole storage into RAM, but normat getItem/setItem does not.
  • If you're looking for the version that supports both synchronous and asynchronous use node-persist@2.1.0

Table of Contents

Install

Example

Change Logs

API

Install

$ npm install node-persist

Basic Example

const storage = require('node-persist');

//you must first call storage.init or initSync
storage.initSync( /* options ... */ );
// or 
// storage.init( /* options ... */ );

// then anywhere else in your code
await storage.setItem('name','yourname')
console.log(await storage.getItem('name')); // yourname

Run the counter example:

$ cd examples/counter
$ node counter.js
$ open up localhost:8080

Change Logs

4.0.0

Non-backward changes

  • Switch file hashes from md5 to sha256

3.1.1

backward changes

  • Added the writeQueue* options, trying to resolve issue#108, see the API Documentation below.

3.0.0

Non-backward changes

  • All the *Sync functions were removed, every operation is now asynchronous
  • All the persist* functions were removed
  • Nothing is held up in RAM use your own memory caching module, i.e. nano-cache
  • Node 7.6+ is required now, we're using async/await
  • continuous and interval options were removed, since we immediately persist to disk now, asynchronously
  • forEach callback now accepts an object callback({key, value}) instead of 2 arguments callback(key, value)

2.0.0

Non-backward changes

  • filenames on the file system are now md5 hashed now and the structure of the saved data has changed to include the ttl in them.
  • no longer need/support a options.ttlDir, since the ttls are now stored in the same file as each value
  • added expiredInterval option
  • added forgiveParseErrors option

1.0.0

Mostly non-backward changes

  • storage.getItem() now returns a promise
  • storage.valuesWithKeyMatch() no longer accepts a callback
  • storage.values() no longer accepts a callback
  • storage.key() is gone
  • The default dir is now process.cwd() + (dir || '.node-persist/storage'), unless you use an absolute path
  • added storage.get(), alias to getItem()
  • added storage.set(), alias to setItem()
  • added storage.del(), storage.rm(), as aliases to removeItem()
  • Keys, on the file system are base64 encoded with the replacement of the /

API Documentation

async init(options, [callback])

if the storage dir is new, it will create it

Options

You can pass init() an options object to customize the behavior of node-persist

These are the defaults

await storage.init({
	// ⚠️ Watch out: The folder should only be used by node-persist and only have valid storage files.
	// Otherwise you might use 'forgiveParseErrors: true'.
	dir: 'relative/path/to/persist',

	stringify: JSON.stringify,

	parse: JSON.parse,

	encoding: 'utf8',

	// can also be custom logging function
	logging: false,  

	// ttl* [NEW], can be true for 24h default or a number in MILLISECONDS or a valid Javascript Date object
	ttl: false,

	// every 2 minutes the process will clean-up the expired cache
	expiredInterval: 2 * 60 * 1000, 

    	// in some cases, you (or some other service) might add non-valid storage files to your
    	// storage dir, i.e. Google Drive, make this true if you'd like to ignore these files and not throw an error
	forgiveParseErrors: false,
	
	// instead of writing to file immediately, each "file" will have its own mini queue to avoid corrupted files, keep in mind that this would not properly work in multi-process setting.
	writeQueue: true, 
	
	// how often to check for pending writes, don't worry if you feel like 1s is a lot, it actually tries to process every time you setItem as well
	writeQueueIntervalMs: 1000, 
	
	// if you setItem() multiple times to the same key, only the last one would be set, BUT the others would still resolve with the results of the last one, if you turn this to false, each one will execute, but might slow down the writing process.
	writeQueueWriteOnlyLast: true, 

	// Limit the number of concurrently used file descriptors to avoid Error: EMFILE: too many open files
	// Defaults to Infinity for maximum performance but YMMV depending on your OS and how you use the library
	maxFileDescriptors: 512
});

async getItem(key)

This function will get the value for that key stored on disk

let value = await storage.getItem('obj');

async setItem(key, value, [options])

This function sets 'key' in your database to 'value'

await storage.setItem('fibonacci',[0,1,1,2,3,5,8]);
await storage.setItem(42,'the answer to life, the universe, and everything.');
await storage.setItem(42,'the answer to life, the universe, and everything.', {ttl: 1000*60 /* 1 min */ });

* The only option available when calling setItem(key, value, option) is {ttl: Number|Date}

async updateItem(key, value, [options])

This function updates a 'key' in your database with a new 'value' without touching the ttl, however, if the key was not found or if it was expired a new item will get set

await storage.updateItem(42,'the answer to life, the universe, and everything.', {ttl: 1000*60*10 /* 10 minutes */ });
await storage.updateItem(42,'means nothing, do not trust wikipedia'); // ttl is still the same, will expired in 10 minutes since it was first set

* The only option available when calling updateItem(key, value, option) is {ttl: Number|Date}

async removeItem(key)

This function immediately deletes it from the file system asynchronously

await storage.removeItem('me');

async clear()

This function immediately deletes all files from the file system asynchronously.

await storage.clear();

async values()

This function returns all of the values

await storage.setItem("batman", {name: "Bruce Wayne"});
await storage.setItem("superman", {name: "Clark Kent"});
console.log(await storage.values()); //output: [{name: "Bruce Wayne"},{name: "Clark Kent"}]

async valuesWithKeyMatch(match)

This function returns all of the values matching a string or RegExp

await storage.setItem("batman", {name: "Bruce Wayne"});
await storage.setItem("superman", {name: "Clark Kent"});
await storage.setItem("hulk", {name: "Bruce Banner"});
console.log(await storage.valuesWithKeyMatch('man')); //output: [{name: "Bruce Wayne"},{name: "Clark Kent"}]
// also accepts a Regular Expression
console.log(await storage.valuesWithKeyMatch(/man/)); //output: [{name: "Bruce Wayne"},{name: "Clark Kent"}]

async keys()

this function returns an array of all the keys in the database.

console.log(await storage.keys()); // ['batman', 'superman']

async length()

This function returns the number of keys stored in the database.

console.log(await storage.length()); // 2

async forEach(callback)

This function iterates over each key/value pair and executes an asynchronous callback as well

storage.forEach(async function(datum) {
	// use datum.key and datum.value
});

Factory method

create(options) - synchronous, static method

If you choose to create multiple instances of storage, you can. Just avoid using the same dir for the storage location. You still have to call init after create - you can pass your configs to either create or init

const storage = require('node-persist');
const myStorage = storage.create({dir: 'myDir', ttl: 3000});
await myStorage.init();

Tests

npm install
npm test
Simon Last