ブラウザーのストレージ制限と削除基準
==================

ウェブ開発者が、ユーザーのブラウザー（つまり、ユーザーがウェブサイトを閲覧するために使用している端末のローカルディスク）にデータを格納するために利用できる技術はたくさんあります。

ブラウザーがウェブサイトに格納することを許可するデータ量と、その制限に達したときにデータを削除するために使用する仕組みは、ブラウザーによって異なります。

この記事では、データを格納するために使用できるウェブ技術、ウェブサイトがデータを格納しすぎないように制限するためにブラウザーが所有しているクォータ、および必要なときにデータを削除するために使用する仕組みについて記述されています。

ブラウザーでは、異なるウェブサイトのデータをどのように区切るのか
--------------------------------

ブラウザーは、ユーザーがウェブ上で追跡されるリスクを縮小するために、ウェブサイトからのデータをさまざまな場所に格納します（バケットとも呼ばれます）。ほとんどの場合、ブラウザーは格納されるデータをオリジンごとに管理します。

このため、オリジンという用語は、この記事を理解する上で重要です。オリジンはスキーム（HTTPS　など）、ホスト名、ポート番号で定義します。例えば、`https://example.com` と `https://example.com/app/index.html` はスキーム (`https`)、ホスト名 (`example.com`) が同じであり、既定のポートであるため、同じオリジンに属します。

この記事で記述されているクォータと退去基準は、このオリジンが `https://example.com/site1/` や `https://example.com/site2/` のように複数のウェブサイトを実行するために使用されている場合でも、オリジン全体に適用されます。

しかし、例えばオリジンが複数の異なるサードパーティ製オリジンの `<iframe>` 要素内に読み込まれる場合など、ブラウザーではオリジンによって格納されるデータをさらに別個のパーティションに分けることができます。しかし、分かりやすいように、この記事では常にオリジンごとにデータが格納されることを想定しています。

ブラウザーにデータを格納する技術は何か
-------------------

ウェブ開発者は、ブラウザーにデータを格納するために以下のウェブ技術を使用することができます。

| 技術 | 説明 |
| --- | --- |
| Cookie | HTTP クッキーは、ウェブサーバーとブラウザーが互いに送信する小さなデータで、ページナビゲーションをまたいで状態情報を記憶します。 |
| ウェブストレージ | ウェブストレージ API は、ウェブページが文字列のみのキーと値のペアを格納するために、`localStorage` と `sessionStorage` を含む機構を提供します。 |
| IndexedDB | IndexedDB は、大規模なデータ構造をブラウザーに格納し、インデックスを作成して高性能な検索を行うためのウェブ API です。 |
| キャッシュ API | キャッシュ API は、HTTP リクエストとレスポンスのオブジェクトペアの持続的な維持メカニズムを提供し、ウェブページの読み込みを高速化するために使用されます。 |
| オリジンプライベートファイルシステム (OPFS) | OPFS は、ページの元に対してプライベートなファイルシステムを提供し、ディレクトリーやファイルを読み書きするために使用することができます。 |

上記に加え、ブラウザーは WebAssembly コードキャッシュなど、オリジンのために他にも型データをブラウザーに格納することに注意してください。

ブラウザーに格納されるデータは維持されるか
---------------------

オリジンのデータはブラウザーに、永続的とベストエフォートという 2 つの方法で格納されます。

* ベストエフォート: これは既定でデータが格納される方法です。ベストエフォートのデータは、オリジンがクォータ以下にあり、機器に十分なストレージ空間が保有され、ユーザーがブラウザー設定からデータの削除を選ばない限り維持されます。
* 永続的: オリジンは、永続的な方法でデータを格納するためにオプトインすることができます。このように格納されたデータは、ユーザーがブラウザー設定を用いて格納することを選んだ場合のみ、削除されます。詳しくは、When is data evictedを参照してください。

オリジンによってブラウザーに格納されるデータは、既定ではベストエフォートです。 IndexedDB やキャッシュなどのウェブ技術を使用する場合、データはユーザーの権限を要求することなく透過的に格納されます。同様に、ブラウザーがベストエフォート型データを削除する必要がある場合、ユーザーにの断りなく削除されます。

何らかの理由で開発者が永続的なストレージを必要とする場合（例えば、他のどこにも維持されていない重要なデータに頼っているウェブアプリケーションを構築する場合）、ストレージ API の `navigator.storage.persist()` メソッドを使用することでそれを行うことができます。

Firefox では、サイトが永続的ストレージを使用することを選ぶと、ユーザーに UI ポップアップでその権限がリクエストされたことが通知されます。

Safari と、ほとんどの Chromium ベースのブラウザー（Chrome や Edge など）は、ユーザーのサイトとの対話履歴に基づいて自動的にリクエストを承認または拒否し、ユーザーにプロンプトを表示させません。

なお、 Chrome チームの調査によると、データがブラウザーによって削除されることはとても稀であることを示しています。ユーザーがウェブサイトを定期的に訪問している場合、ベストエフォートモードであっても、格納されるデータがブラウザーによって取得される可能性はとても低いのです。

### プライベートブラウジング

プライベートブラウジングモード（Chrome では *Incognito*、 Edge では *InPrivate* とも呼ばれる）では、ブラウザーによって異なるクォータが適用されることがあり、格納されるデータは通常、プライベートブラウジングモードが終わると削除されることに注意してください。

どれだけのデータが格納できるか
---------------

### Cookie

ブラウザーごとに、オリジンごとに許可されるクッキーの数と、これらのクッキーがディスク上で使用できる空間について、異なる規則があります。クッキーはブラウザーとウェブサーバーの間でページナビゲーションにわたって小さな共有状態を保持するのに有益なものですが、ブラウザーのデータ格納のためにクッキーを使用することはお勧めできません。クッキーは HTTP リクエストごとに送信されるため、別のウェブ技術を使用することで格納できるデータをクッキーに格納すると、リクエストのサイズが不必要に大きくなります。

クッキーはブラウザーにデータを格納するために使用すべきではありませんから、クッキーの格納ブラウザーの制限はここでは取り上げません。

### ウェブストレージ

ウェブストレージは、 `Window` オブジェクトの `localStorage` および `sessionStorage` プロパティを使用してアクセスすることができ、すべてのブラウザーでデータ量が最大 10MiB に制限されています。

ブラウザーはローカルストレージを 5MiB まで、オリジンごとにセッションストレージを 5MiB まで格納することができます。

この制限に達すると、ブラウザーは `QuotaExceededError` 例外を発生します。これは `try...catch` ブロックを使用して処理しましょう。

### その他のウェブ技術

IndexedDB、キャッシュ API、ファイルシステム API（オリジンプライベートファイルシステムを定義する）などの他にもウェブ技術を使用して格納されるデータは、各ブラウザー固有のストレージ管理システムによって管理されます。

このシステムはこれらの API を使用してオリジンが格納するすべてのデータを管理します。

それぞれのブラウザーは、指定されたオリジンが使用することができるストレージの最大量を、あらゆるメカニズムを使って決定します。

#### Firefox

Firefox では、ベストエフォートモードでオリジンが使用できる最大ストレージ空間は、以下のいずれか小さい方です。

* ユーザーのプロファイルが格納されるディスク総容量の 10%。
* または、 10GiB は Firefox が同じ eTLD+1 ドメイン (en-US)に属するすべてのオリジンに適用するグループ制限です。

永続的ストレージが許可されているオリジンは、総ディスクサイズの 50% （上限 8 TiB）まで格納することができ、eTLD+1 グループの制限を受けません。

例えば、端末に 500 GiB のハードドライブがある場合、 Firefox はオリジンに以下の量まで格納することを許可します。

* ベストエフォートモードの場合: eTLD+1 グループの制限である 10GiB のデータ。
* 永続モードの場合: 250 ギガバイト（ディスク総サイズの 50%）。

クォータは現在利用できるディスク空間ではなく、ハードドライブの**総**サイズに基づいて計算されるため、オリジンがそのクォータに到達することは実際には不可能かもしれないことに注意してください。これはセキュリティ上の理由からフィンガープリンティングを避けるために行われます。

#### Chrome および Chromium ベースのブラウザー

Chrome や Edge を含む Chromium オープンソースプロジェクトに基づくブラウザーでは、オリジンは永続モードとベストエフォートモードの両方で、総ディスクサイズの 60% まで格納することができます。

例えば、機器に 1TiB のハードドライブがある場合、ブラウザーは一つのオリジンが 600GiB まで使用することを許可します。

Firefox と同様に、このクォータはフィンガープリントを避けるためにハードドライブの合計サイズに基づいて計算されるため、オリジンは実際にはクォータに到達しない可能性があります。

#### Safari

Safari では、オリジンには最初に 1GiB のクォータが指定されます。オリジンがこの制限に達すると、 Safari はユーザーに、オリジンがさらにデータを格納するためにその権限を要求します。これは、オリジンがデータを格納するのがベストエフォートモードでも永続モードでも発生します。

利用可能な空間をチェックする方法
----------------

ウェブ開発者は、このオリジンで利用可能な空間がどれくらいか、オリジンがどれだけ使用しているかをストレージ API の`navigator.storage.estimate()`メソッドで調べることができます。

このメソッドは使用量の推定値のみを返し、実際の値を返さないことに注意してください。オリジンによって格納されるリソースの一部は、他にもオリジンから来る可能性があり、ブラウザーは総使用値を報告する際に、自発的にオリジン間データのサイズをパディングします。

オリジンがクォータを使い切った場合はどうなるか
-----------------------

例えば、IndexedDB、キャッシュ、OPFS を使用して、オリジンのクォータを超えて格納しようとすると、`QuotaExceededError` 例外が発生して失敗します。

ウェブ開発者はブラウザーストレージに書き込む JavaScript を `try...catch` ブロックで囲むべきです。新しいデータを格納するために、データを削除して空間を解放することも推奨されます。

データが退去されるのはいつか
--------------

データ退去とは、ブラウザーがオリジンの格納されるデータを削除するプロセスです。

データ消去は複数のケースで発生します。

* 端末の記憶領域が残り少なくなっているとき。
* ブラウザーに（すべてのオリジンにわたって）格納されるすべてのデータが、ブラウザーが端末上で使用するために必要な空間の大きさを超えた場合。
* 定期的に使用していないオリジンについては、 Safari でのみ発生します。
### ストレージ圧縮による退去

ストレージ圧縮とも呼ばれるように、端末のストレージ空間が不足している場合、ブラウザーが利用できる領域がオリジンの格納されるデータをすべて保存するのに必要な領域よりも少なくなる点があります。

ブラウザーは、このシナリオに対処するために LRU (Least Recently Used) ポリシーを使用します。最も最近使用したオリジンのデータは削除されます。ストレージの圧縮が続く場合、ブラウザーは 2 つ目に最も最近使用したオリジンに移動し、問題が解決するまでこれを繰り返します。

この退去メカニズムは、永続的でないオリジンにのみ適用され、 `navigator.storage.persist()` を使用してデータの永続性を付与されたオリジンはスキップされます。

### ブラウザーストレージの最大値を超えたことによる退去

ブラウザーによっては、端末のハードディスクで使用できる最大ストレージ空間を定義しています。例えば、Chromeは現在、全ディスクサイズの最大80%を使用しています。

この最大ストレージサイズは、すべてのオリジンの組み合わせによって格納されるデータが、どのオリジンも個々の割り当てを超えることなく、最大サイズを超える点があることを意味しています。

この場合、ブラウザーはストレージ圧縮による退去で記述されているように、ベストエフォート型オリジンの削除を開始します。

### 積極的な退去

Safari は、クロスサイトトラッキング防止がオンになっている場合、積極的にデータを消去します。ブラウザーが使用されてから 7 日以内にクリックやタップなどのユーザー対話がなかったオリジンは、スクリプトから作成されたデータが削除されます。サーバーによって設定されたクッキーは、この削除の対象から除外されます。

データはどのように消去されるのか
----------------

オリジンのデータがブラウザーによって削除される場合、データの一部ではなく、すべてのデータが同時に削除されます。例えばオリジンが IndexedDB とキャッシュ API を使用してデータを格納していた場合、両方の種類のデータが削除されます。

元のデータの一部だけを削除すると、不整合の問題が発生する可能性があるからです。

関連情報
----

* ウェブのストレージ (web.dev)
* 永続的ストレージ (web.dev)
* Chrome Web Storage and Quota Concepts