---
title: "クラウドセーブ"
description: "セーブは、利用者（API の名前では players = プレイヤー）ごとにスロットキー（`slot1`、`profile`、`settings`…）の下に保存されるJSONドキュメントです。"
url: "/ja/docs/guides/saves/"
lang: ja
index: "/ja/llms.txt"
---
# クラウドセーブ

セーブは、利用者（API の名前では players = プレイヤー）ごとに**スロットキー**（`slot1`、`profile`、`settings`…）の下に保存されるJSONドキュメントです。文書・利用者の設定・下書き・ゲームの進行などを入れられます。セーブは利用者がログインするすべての端末についていき、各スロットは**バージョン**を持つので、2つの端末が互いの内容を黙って上書きすることはありません。

## 読み書き

```js
const save = await kumo.saves.get('slot1');        // スロットがまだ無ければ null
const state = save?.data ?? { level: 1, hp: 3 };

state.level += 1;
await kumo.saves.set('slot1', state);              // 最後の書き込みが勝つ
```

| メソッド | 戻り値 |
|---|---|
| `saves.get(key)` | `{ key, version, size, updatedAt, data }`または`null` |
| `saves.set(key, data, { ifVersion? })` | `{ key, version, size, updatedAt }` |
| `saves.list()` | `[{ key, version, size, updatedAt }]`（dataなし） |
| `saves.delete(key, { ifVersion? })` | — |

## 競合に強い書き込み

シンプルな形は上書きです。利用者が2つの端末で同時に使う可能性があるときは、`ifVersion`を付けて書きます。

```js
try {
  await kumo.saves.set('profile', profile, { ifVersion: 'latest' });
} catch (e) {
  if (e.code !== 'version_conflict') throw e;
  const cloud = await kumo.saves.get('profile');   // 別の誰かが先に書いた
  profile = merge(cloud.data, profile);            // どうマージするかはアプリが決める
  await kumo.saves.set('profile', profile, { ifVersion: cloud.version });
}
```

- `ifVersion: 'latest'` — このSDKインスタンスがそのスロットで最後に見たバージョン（一度も読んでいなければ0）
- `ifVersion: <number>` — 保存されているバージョンがこの値と等しいときだけ書く。`0`は「スロットが存在しないときだけ」
- 一致しない場合、サーバーは`details.currentVersion`付きの**409 `version_conflict`**を返します

## 上限

| 上限 | 値 |
|---|---|
| 利用者あたりのスロット数 | 32（`too_many_saves`） |
| スロットあたりのサイズ | JSONで256 KB（`save_too_large`、HTTP 413。`details.size`と`details.limit`付き）。SDKは送る前にバイト数を数え、同じエラーを送らずに投げます。SDKを通さずに1 MBを超える本文を送ると413 `invalid_request`です |
| スロットキー | 小文字のsnake_case。英字で始まり、以降は`a-z`、`0-9`、`_`。最大48文字 |

セーブは環境ごとに分かれています。developmentのセーブがproductionに現れることはありません。

## セーブか、自分のデータベースか

セーブを書くのは利用者自身のブラウザです。書き換えたページからは何でも入れられます。だれが書き換えてよいかで選んでください。

**守るものは D1 に。saves には入れない。** 利用者が自分で書き換えてはいけないもの（スコアとランキング・コイン・クレジット・アイテム・購入・バッジ・利用者どうしで共有するもの）は、プロジェクト自身の Functions + D1 に置く。`saves` に置くのは、利用者が自由に書いてよいもの（設定・下書き・1 人で遊ぶゲームの進み具合）だけ。

| 置く場所 | 何を | だれが書くか |
|---|---|---|
| **セーブ** | 利用者が自由に変えてよいもの: 設定、進み具合のメモ、下書き、お気に入り、ゲームのセーブ | 利用者のブラウザ（書き換えられても困らない） |
| [Functions](/ja/docs/guides/functions/index.md)の**自分のデータベース**（D1） | 守るべきもの: スコアと順位、コイン、クレジット、アイテム、購入、認証済みのバッジ、利用者どうしで共有するもの | 自分のサーバーのコードだけ |

迷ったら: 利用者が手で書き換えると困るなら、自分のデータベースに置きます。セーブが持つのは*状態*で、*通貨*ではありません。自分のサーバーのコードから利用者のセーブは読み書きできないので、守るべきものは最初から自分のデータベースに置いてください。
