# Storage quotas, persistence, and eviction

> Compare storage limits, persistent mode, and eviction rules in Chromium, Firefox, and WebKit, with runtime checks and recovery paths.

Storage quota limits how much an origin can write, persistence primarily changes whether its bucket is eligible for automatic clearing, and eviction removes stored data under a browser's clearing policy. Quota remains implementation-defined and can depend on persistent-storage permission, so a successful persistence request may also change the origin's quota. Firefox, for example, applies a higher limit after persistent storage is granted.

The compatibility table for this entry uses the `api.StorageManager.persist` data in [Persistent Storage](/compatibility/persistent-storage/).

## How it works

The Storage Standard gives each storage shelf a default bucket. A local storage bucket's mode is `best-effort` or `persistent`. It defines usage as an implementation-defined rough estimate and quota as an implementation-defined conservative estimate. Compression, deduplication, and privacy protections mean the values returned by `estimate()` are not an exact view of disk blocks ([Storage Standard](https://storage.spec.whatwg.org/#usage-and-quota), storage.spec.whatwg.org).

Persistence protects a local storage bucket from clearing by the user agent without involvement from the origin or user. The standard still permits the user to clear it. The `persist()` method requests the `persistent-storage` permission and resolves to a boolean that reports whether the default bucket is persistent; `persisted()` reads that mode without requesting a change ([Storage Standard](https://storage.spec.whatwg.org/#persistence), storage.spec.whatwg.org).

Eviction applies to storage the browser manages by origin, including IndexedDB, Cache Storage, and the Origin Private File System. When a browser evicts an origin, MDN documents that it deletes the origin's managed data together instead of trimming one database. The Storage Standard likewise requires a bucket to be cleared in its entirety ([Storage quotas and eviction criteria](https://developer.mozilla.org/en-US/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria), developer.mozilla.org; [Storage Standard](https://storage.spec.whatwg.org/#management), storage.spec.whatwg.org).

| Decision | Question to answer | Browser signal | Application response |
|---|---|---|---|
| Quota | Can the next write fit? | `navigator.storage.estimate()` gives approximate `usage` and `quota`. | Catch the write error and offer cleanup or server recovery. |
| Persistence | May the browser automatically clear this bucket? | `persisted()` reports the mode; `persist()` requests a change. | Keep critical local-only work recoverable until the result is `true`. |
| Eviction | What happens when the browser needs space? | There is no eviction event in the Storage Standard. | On startup, validate the records and caches the app needs, then rebuild missing data. |

### Chromium policy

Chrome's storage guidance states that Chrome lets the browser use up to 80% of total disk space and lets an origin use up to 60%. It also states that best-effort origins are cleared in least-recently-used order when the browser runs out of space. Those figures describe Chrome's policy, while other Chromium-based browsers can differ ([Storage for the web](https://web.dev/articles/storage-for-the-web), web.dev).

Chrome and other Chromium browsers normally decide a persistence request from site-engagement signals without showing a permission prompt. A returned `false` leaves the bucket in best-effort mode; it does not mean that a write has failed ([Storage quotas and eviction criteria](https://developer.mozilla.org/en-US/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria), developer.mozilla.org).

### Firefox policy

MDN records Firefox best-effort storage as the smaller of 10% of the disk that holds the profile or the 10 GiB group limit shared by origins in the same site. Persistent origins can use up to 50% of total disk, capped at 8 TiB, and are not subject to that group limit. Firefox asks the user when a site requests persistent storage. Under storage pressure, it skips persistent origins and evicts best-effort origins in least-recently-used order ([Storage quotas and eviction criteria](https://developer.mozilla.org/en-US/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria), developer.mozilla.org).

Firefox calculates the quota from total disk size. An origin can therefore receive an estimate larger than the space that can actually be written. Code still needs to handle a failed write after a reassuring estimate.

### WebKit policy

WebKit documents separate origin and overall quotas. Starting in Safari 17.0 and WebKit apps for iOS 17, iPadOS 17, and macOS Sonoma, a browser app's origin quota is up to 60% of total disk and its overall quota is up to 80%. Other apps that embed web content receive lower limits. A standalone Home Screen web app on iOS or a web app added to the Dock on macOS receives the same origin and overall quota as the site in a browser app ([Updates to Storage Policy](https://webkit.org/blog/14403/updates-to-storage-policy/), webkit.org).

WebKit names overall-quota pressure, system storage pressure, and Intelligent Tracking Prevention as paths that can delete website data. Its ITP documentation says that, from iOS and iPadOS 13.4 and Safari 13.1 on macOS, seven days of Safari use without interaction with a site causes deletion of its script-writable storage. Home Screen web apps have their own counter of days of use ([Full Third-Party Cookie Blocking and More](https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/), webkit.org).

:::caution
Reaching an origin quota and losing data to eviction are different failure paths. WebKit says a write that needs more space than the origin quota throws `QuotaExceededError`; reaching the overall quota can lead to eviction. Catch `QuotaExceededError` at the write and also validate stored state on a later launch ([Updates to Storage Policy](https://webkit.org/blog/14403/updates-to-storage-policy/), webkit.org).
:::

## Examples

The first example reports the mode and the estimate without treating either value as a promise that a later write will succeed.

### Inspecting quota and persistence

```js
async function readStorageState() {
  if (!navigator.storage?.estimate) {
    return { supported: false, persisted: false };
  }

  const { usage = 0, quota = 0 } = await navigator.storage.estimate();
  const persisted = navigator.storage.persisted
    ? await navigator.storage.persisted()
    : false;

  return { supported: true, usage, quota, persisted };
}

readStorageState().then((state) => console.log(state));
```

The fallback returns a state the interface can label as unavailable. When support exists, `usage` and `quota` remain estimates in bytes; the application can display them without deriving a guaranteed amount for its next transaction.

The second example requests persistence and handles a quota failure separately. It preserves the draft on the server when local storage cannot accept it.

### Recovering when a write exceeds quota

```js
async function saveDraft(draft) {
  const persistent = navigator.storage?.persist
    ? await navigator.storage.persist()
    : false;

  try {
    await draftsDatabase.put(draft);
    return { saved: 'local', persistent };
  } catch (error) {
    if (error?.name !== 'QuotaExceededError') throw error;
    await fetch('/api/drafts', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify(draft),
    });
    return { saved: 'server', persistent };
  }
}
```

The persistence result and the write result stay independent. A `false` persistence result can accompany a successful write, while `QuotaExceededError` takes the explicit recovery branch described by Chrome's and WebKit's storage guidance.

On the next launch, check for application-level records. `estimate()` alone cannot identify eviction. A missing database can also mean a first visit or a user-initiated clear. [Eviction and best-effort storage](/reference/storage/eviction/) covers that recovery boundary, and [Safari's 7-day cap on script-writable storage](/reference/storage/safari-seven-day-cap/) covers WebKit's proactive path.

## See also

- [Storage Standard](https://storage.spec.whatwg.org/) (storage.spec.whatwg.org)
- [Updates to Storage Policy](https://webkit.org/blog/14403/updates-to-storage-policy/) (webkit.org)
- [Storage for the web](https://web.dev/articles/storage-for-the-web) (web.dev)
- [StorageManager.persist() and persisted()](/reference/storage/persistence/)
- [StorageManager.estimate()](/reference/storage/quota-estimate/)
- [Eviction and best-effort storage](/reference/storage/eviction/)
- [Persistent Storage compatibility](/compatibility/persistent-storage/)