docs/articles/localstorage.md
This guide explores localStorage in JavaScript web apps, detailing its usage, limitations, and alternatives like IndexedDB and AsyncStorage.
When it comes to client-side storage in web applications, the localStorage API stands out as a simple and widely supported solution. It allows developers to store key-value pairs directly in a user's browser. In this article, we will explore the various aspects of the localStorage API, its advantages, limitations, and alternative storage options available for modern applications.
<center> </center>The localStorage API is a built-in feature of web browsers that enables web developers to store small amounts of data persistently on a user's device. It operates on a simple key-value basis, allowing developers to save strings, numbers, and other simple data types. This data remains available even after the user closes the browser or navigates away from the page. The API provides a convenient way to maintain state and store user preferences without relying on server-side storage.
Let's dive into some hands-on code examples to better understand how to leverage the power of localStorage. The API offers several methods for interaction, including setItem, getItem, removeItem, and clear. Consider the following code snippet:
// Storing data using setItem
localStorage.setItem('username', 'john_doe');
// Retrieving data using getItem
const storedUsername = localStorage.getItem('username');
// Removing data using removeItem
localStorage.removeItem('username');
// Clearing all data
localStorage.clear();
While js localStorage excels at handling simple key-value pairs, it also supports more intricate data storage through JSON serialization. By utilizing JSON.stringify and JSON.parse, you can store and retrieve structured data like objects and arrays. Here's an example of storing a document:
const user = {
name: 'Alice',
age: 30,
email: '[email protected]'
};
// Storing a user object
localStorage.setItem('user', JSON.stringify(user));
// Retrieving and parsing the user object
const storedUser = JSON.parse(localStorage.getItem('user'));
Despite its convenience, localStorage does come with a set of limitations that developers should be aware of:
Contrary to concerns about performance, the localStorage API in JavaScript is surprisingly fast when compared to alternative storage solutions like IndexedDB or OPFS. It excels in handling small key-value assignments efficiently. Due to its simplicity and direct integration with browsers, accessing and modifying localStorage data incur minimal overhead. For scenarios where quick and straightforward data storage is required, localStorage remains a viable option. For example RxDB uses localStorage in the localStorage meta optimizer to manage simple key values pairs while storing the "normal" documents inside of another storage like IndexedDB.
While localStorage offers convenience, it may not be suitable for every use case. Consider the following situations where alternatives might be more appropriate:
new Map() or new Set(). These options offer speed and efficiency for transient data.While localStorage serves as a reliable storage solution for simpler data needs, it's essential to explore alternatives like IndexedDB when dealing with more complex requirements. IndexedDB is designed to store not only key-value pairs but also JSON documents. Unlike localStorage, which usually has a storage limit of around 5-10MB per domain, IndexedDB can handle significantly larger datasets. IndexDB with its support for indexing facilitates efficient querying, making range queries possible. However, it's worth noting that IndexedDB lacks observability, which is a feature unique to localStorage through the storage event. Also,
complex queries can pose a challenge with IndexedDB, and while its performance is acceptable, IndexedDB can be too slow for some use cases.
// localStorage can observe changes with the storage event.
// This feature is missing in IndexedDB
addEventListener("storage", (event) => {});
For those looking to harness the full power of IndexedDB with added capabilities, using wrapper libraries like RxDB is recommended. These libraries augment IndexedDB with features such as complex queries and observability, enhancing its usability for modern applications by providing a real database instead of only a key-value store.
<center> </center>In summary when you compare IndexedDB vs localStorage, IndexedDB will win at any case where much data is handled while localStorage has better performance on small key-value datasets.
Another intriguing option is the OPFS (File System API). This API provides direct access to an origin-based, sandboxed filesystem which is highly optimized for performance and offers in-place write access to its content. OPFS offers impressive performance benefits. However, working with the OPFS API can be complex, and it's only accessible within a WebWorker. To simplify its usage and extend its capabilities, consider using a wrapper library like RxDB's OPFS RxStorage, which builds a comprehensive database on top of the OPFS API. This abstraction allows you to harness the power of the OPFS API without the intricacies of direct usage.
Cookies, once a primary method of client-side data storage, have fallen out of favor in modern web development due to their limitations. While they can store data, they are about 100 times slower when compared to the localStorage API. Additionally, cookies are included in the HTTP header, which can impact network performance. As a result, cookies are not recommended for data storage purposes in contemporary web applications.
WebSQL, despite offering a SQL-based interface for client-side data storage, is a deprecated technology and should be avoided. Its API has been phased out of modern browsers, and it lacks the robustness of alternatives like IndexedDB. Moreover, WebSQL tends to be around 10 times slower than IndexedDB, making it a suboptimal choice for applications that demand efficient data manipulation and retrieval.
In scenarios where data persistence beyond a session is unnecessary, developers often turn to sessionStorage. This storage mechanism retains data only for the duration of a tab or browser session. It survives page reloads and restores, providing a handy solution for temporary data needs. However, it's important to note that sessionStorage is limited in scope and may not suit all use cases.
For React Native developers, the AsyncStorage API is the go-to solution, mirroring the behavior of localStorage but with asynchronous support. Since not all JavaScript runtimes support localStorage, AsyncStorage offers a seamless alternative for data persistence in React Native applications.
node-localstorage for Node.jsBecause native localStorage is absent in the Node.js JavaScript runtime, you will get the error ReferenceError: localStorage is not defined in Node.js or node based runtimes like Next.js. The node-localstorage npm package bridges the gap. This package replicates the browser's localStorage API within the Node.js environment, ensuring consistent and compatible data storage capabilities.
While browser extensions for chrome and firefox support the localStorage API, it is not recommended to use it in that context to store extension-related data. The browser will clear the data in many scenarios like when the users clear their browsing history.
Instead the Extension Storage API should be used for browser extensions.
In contrast to localStorage, the storage API works async and all operations return a Promise. Also it provides automatic sync to replicate data between all instances of that browser that the user is logged into. The storage API is even able to storage JSON-ifiable objects instead of plain strings.
// Using the storage API in chrome
await chrome.storage.local.set({ foobar: {nr: 1} });
const result = await chrome.storage.local.get('foobar');
console.log(result.foobar); // {nr: 1}
The Deno JavaScript runtime has a working localStorage API so running localStorage.setItem() and the other methods, will just work and the locally stored data is persisted across multiple runs.
Bun does not support the localStorage JavaScript API. Trying to use localStorage will error with ReferenceError: Can't find variable: localStorage. To store data locally in Bun, you could use the bun:sqlite module instead or directly use a in-JavaScript database with Bun support like RxDB.
In the world of modern web development, localStorage serves as a valuable tool for lightweight data storage. Its simplicity and speed make it an excellent choice for small key-value assignments. However, as application complexity grows, developers must assess their storage needs carefully. For scenarios that demand advanced querying, complex data structures, or high-volume operations, alternatives like IndexedDB, wrapper libraries with additional features like RxDB, or platform-specific APIs offer more robust solutions. By understanding the strengths and limitations of various storage options, developers can make informed decisions that pave the way for efficient and scalable applications.
Both localStorage and sessionStorage provide synchronous, key-value storage capabilities built natively into the web browser. The primary difference is their lifespan: data in LocalStorage persists indefinitely until explicitly cleared by the application or the user. Data in SessionStorage, however, is strictly bound to the specific browser tab that created it and is instantly deleted the moment you close the tab.
Yes, localStorage inherently adheres to the browser's strict Same-Origin Policy. All stored data is tightly sandboxed by the exact combination of the protocol, hostname, and port. For example, scripts loaded on https://example.com are physically unable to access data stored by http://example.com (different protocol) or https://app.example.com (different subdomain).
LocalStorage only officially supports storing string values. To store structured data like JSON objects or arrays, you must serialize them to a string using JSON.stringify() before storage and parse them with JSON.parse() upon retrieval. You cannot store binary formats like Files or Blobs directly; they must either be converted to a Base64 string, which is inefficient and bulky, or natively stored using IndexedDB or OPFS instead.
No, data saved in LocalStorage is confined entirely to the local storage hardware of the specific device and browser profile that created it. It does not automatically synchronize to the cloud or other devices. To seamlessly sync locally stored data across multiple clients, you need a sync-ready database like RxDB that automatically replicates the document state to a central backend server.
</details> <details> <summary>Is LocalStorage persistent across browser sessions and tabs?</summary>Yes, data in localStorage persists across entirely different browser sessions. Even if a user closes their tab, quits their browser application, or reboots their system, the data remains intact whenever they return. Furthermore, any changes made to localStorage in one tab are immediately available to all other active tabs operating under the identically formatted origin string.
Data in localStorage persists indefinitely. The API does not provide any native automatic expiration or Time-to-Live (TTL) mechanisms. If you need data to expire automatically after a specific time frame, you must manually save a timestamp alongside your data payload and implement your own JavaScript verification logic to delete the item when the operational threshold is passed.
No. Because LocalStorage strictly enforces the Same-Origin Policy, it physically cannot pass or share data across completely different domains or even subdomains out-of-the-box. The origin string (comprising the scheme, hostname, and port) must match exactly. Sharing real-time data or state across separate domains usually requires complex workarounds involving hidden <iframe>s combined with window.postMessage(), or utilizing a highly capable database synchronization protocol.
No, LocalStorage does not require any backend environment, server, or database to function. It is a completely self-contained browser API that stores data strictly on the client's local device. However, if you need this data to sync to other devices or back up to the cloud, you will need a backend infrastructure in place.
</details>