- AIが扱う音声・文字起こしのようなデータは、保存して使う設計が先に固まり、消す設計は後回しになりやすい。消す仕組みは動いている間は誰の目にも触れず、価値を生まないという構造そのものが原因になる。
- 配布は公開バケットではなく署名付きURLで期限を切って渡す。ただし署名付きURLはS3互換エンドポイントでしか発行できず、カスタムドメインでは使えないという制約がある。
- 自動削除はObject Lifecycle、消してはいけないデータはBucket Locksで守る。同じオブジェクトに重ねるとBucket Lockが優先されるため、優先順位を理解せずに設計すると事故につながる。
AIが扱うデータの保持期間は、なぜ設計が後回しになるのか?
消す仕組みは動いている間は誰にも価値を生まないため後回しにされ、たいてい情シス審査や削除依頼で初めて問われて詰まるから。
音声を文字起こしする、面談の記録を要約する、相談内容から下書きを作る——生成AIを使ったサービスは、たいてい「保存して使う」機能が先に完成する。文字起こしの精度も、検索も、要約の質も、保存されたデータの上に成り立つ体験だから、開発の優先順位は自然と「入れる・使う」側に寄っていく。
一方で「消す」機能は、動いている間はユーザーにも開発チームにも何の価値も生まない。それどころか、実装とテストの手間が増えるだけに見える。優先順位をつけるとき、後ろに回されやすい理由はここにある。バグではなく、構造として後回しにされる。
後回しにされたツケが表面化するタイミングは、だいたい決まっている。情シス審査のセキュリティチェックシートで「保持期間」「削除方針」の欄に答えられないとき。個人情報保護方針を見直すとき。退職者や解約した顧客から削除を求められたとき。監査で「誰のデータをいつまで持っているか」を聞かれたとき。どれも、サービスが順調に育った後にやってくる。
さらにAIを扱うサービス特有の事情もある。保存先を1つ決めれば済んだ時代と違い、音声や文字起こしのような一次データに加えて、要約や下書きの生成のために外部のAIプロバイダへ送信したコピー、CDNやアプリ側のキャッシュ、アクセスログといった「増殖したコピー」が生まれる。保存先を決めることと、保持・削除のライフサイクルを設計することは、似ているようで別の仕事だ。
保存先を1つ決めることは、プロダクトが動くための条件。保持・削除のライフサイクルを設計することは、動き続けた先で必ず問われる条件。両方をひとつの「保存の設計」として扱った瞬間に、消す側の設計だけが静かに抜け落ちる。
ここから先は、Cloudflare R2を例に、保持と削除をどう設計するかを機能ごとに見ていく。本稿のR2機能に関する記述は、2026年8月時点のCloudflare公式ドキュメント(developers.cloudflare.com)に基づく——製品仕様は更新されるため、導入判断の直前には必ず一次情報を確認してほしい。
音声・文字起こしは、どこに置き、どう配布すればよいのか?
バケットを公開状態にせず、配布は署名付きURLで期限を切って渡す。ただしカスタムドメインでは署名付きURLが使えない制約がある。
R2バケットには、公開アクセスを有効にしてURLで直接配信する設定と、非公開のまま必要なときだけ一時的なURLを発行する設定がある。音声や文字起こしのような機微なデータを扱うなら、基本は後者になる。バケットを公開状態にしたうえで「推測されにくいURLだから大丈夫」という運用は、URLさえ知っていれば誰でも入れる状態と実質同じで、URLは共有チャットやログ、ブラウザ履歴といった思わぬ経路から漏れうる。
署名付きURL(presigned URL)は、この問題への標準的な答えだ。有効期限を1秒〜7日間(604,800秒)の範囲で指定して発行するURLで、期限が切れれば自動的に使えなくなる。URLに含まれるリソース・操作(GETやPUTなど)・期限のいずれかが書き換えられると署名が一致しなくなり、403 SignatureDoesNotMatchで拒否される。発行にはAWS SDK for JavaScript v3のgetSignedUrlとGetObjectCommandを使い、regionには"auto"を指定する。
図:署名付きURL発行の流れ(イメージ)。1回の発行につき1つのリソース・1つの有効期限が紐づき、期限を過ぎればURLごと無効になる。
ここで実務上ハマりやすいのが、署名付きURLはS3互換エンドポイント({ACCOUNT_ID}.r2.cloudflarestorage.com)でのみ発行でき、カスタムドメインを設定したバケットでは使えないという制約だ。ブランドを統一するために配信用ドメインをカスタムドメインへ切り替えた直後、「署名付きURLの発行コードが動かなくなった」というつまずきは珍しくない。原因はコードのバグではなく、エンドポイントの選び方そのものにある。配布に署名付きURLを使う設計なら、カスタムドメインとは別に、発行専用でS3互換エンドポイントを使う経路を最初から用意しておく必要がある。
もう一つ、実務でよく見落とされるのがバケット名を決めるタイミングだ。Cloudflareの仕様上、R2バケットの名前は作成後に変更できない。プロダクト名やブランドを変更しても、既存バケットの名前はそのまま残る。筆者が運営するAIインタビューサービスでも、プロダクトの改名後に旧サービス名を含むバケット名をそのまま使い続けている。バケット名は署名付きURLの外部露出がなければユーザーの目に触れないため、実害がないと判断してそのままにした、という実務上の判断だ。バケットを作る最初の一手は、後から直せないという前提で決めておくとよい。
| 配布方法 | アクセスできる人 | 主なリスク | 向いている用途 |
|---|---|---|---|
| 公開バケット+直リンク | URLを知っている全員(推測も含む) | URLの流出がそのまま無制限アクセスにつながる | 公開して問題ない静的アセットのみ |
| 署名付きURL | URLを知っていて、かつ有効期限内の人 | 期限内はURLを知る人なら誰でもアクセス可能 | 一時的な個別配布・ダウンロードリンク |
| Cloudflare Access等の認証経由 | IdPで認証された本人のみ | 導入・運用の手間はやや大きい | 継続的な社内アクセス・管理画面 |
継続的に社内メンバーがアクセスする管理画面のような用途では、署名付きURLよりもリクエストごとに人を確認する構成のほうが向いている。その設計は社内ツール・管理画面をVPNなしで守るで扱っている。本稿が扱うのは、あくまで音声・文字起こしのような個々のファイルを一時的に配る場面での設計だ。
保持期間が過ぎたデータは、どう自動で消すのか?
Object Lifecycleでルールを設定して自動削除・保存クラス移行を行う。ただしprefix設計を先に決めておかないとルールが作れない。
保持期間が来たデータを人力で消す運用は、件数が増えた瞬間に破綻する。R2のObject Lifecycleは、この作業をルールとして仕組み化する機能だ。設定はダッシュボード・Wrangler CLI・S3互換のLifecycle APIの3経路から行え、1バケットあたり最大1,000ルールを持てる。ルールの種類は2つ——期限が来たオブジェクトを削除するExpirationと、標準ストレージから低頻度アクセス(Infrequent Access)クラスへ移すTransition——で、削除だけでなくコスト最適化のためのクラス移行もあわせて設計できる。
図:Wrangler CLIでのLifecycleルール追加イメージ。ルールはバケット全体ではなくprefix単位で適用範囲を決める。
ここで効いてくるのがprefix設計だ。LifecycleルールはPrefix(フォルダのような区切り)単位で適用範囲を決める。音声は90日、文字起こしのテキストは1年、一時的なエクスポートファイルは7日、というように、データの種類ごとに保持期間が違うのであれば、その種類ごとにprefixを最初から分けておく必要がある。「バケットを1つ作って、種類を区別せず全部同じ場所に放り込む」設計だと、あとからルールを作る段階で詰む——特定の種類だけを狙って削除する手段がなくなるからだ。
| ルール種別 | 何をするか | 主なオプション | 使いどころ |
|---|---|---|---|
| Expiration | 指定した日数・日付が来たオブジェクトを削除 | --expire-days/--expire-date | 保持期間が過ぎた音声・文字起こし・一時ファイルの自動削除 |
| Transition | 標準ストレージから低頻度アクセスクラスへ移行 | --ia-transition-days | 削除はしないが、参照頻度が下がった過去データのコスト最適化 |
見落とされがちだが地味に効くのが--abort-multipart-daysだ。アップロードに失敗した音声ファイルの断片(マルチパートアップロードの未完了分)は、放置すると気づかないまま課金対象のストレージとして残り続ける。保持期間の設計と同じタイミングで、このオプションも一緒に決めておくと後で困らない。
prefix設計は、保存を始める前に一度決めてしまえば、あとはルールを積むだけの話になる。逆に、保存が始まってから設計をやり直すコストは、オブジェクトの数だけ膨らむ。
消してはいけないデータは、どう守るのか?
Bucket Locksで削除・上書きを禁止する。Object Lifecycleと同じオブジェクトに設定した場合はBucket Lockが優先されるため、順序を誤ると「消えるはずが消えない」事故が起きる。
自動削除の設計を進めると、今度は逆の要件にぶつかる。監査ログ、契約上の保存義務があるデータ、法的な保全要請がかかったデータのように、「期限が来ても消えては困る」データだ。これに応えるのがBucket Locksで、Object Lifecycleとは別の仕組みとして用意されている。指定した期間、あるいは無期限で、オブジェクトの削除・上書きそのものを禁止する保持機能で、ダッシュボード・wrangler r2 bucket lock addコマンド・APIから設定でき、1バケットあたり最大1,000ルールを持てる。
| 観点 | Object Lifecycle | Bucket Locks |
|---|---|---|
| 役割 | 期限が来たら消す・移す | 期限が来ても消させない・変更させない |
| 典型的な用途 | 音声・文字起こしなど通常データの保持期間運用 | 監査ログ、契約上の保存義務があるデータ、保全要請中のデータ |
| 設定経路 | ダッシュボード/Wrangler CLI/S3互換Lifecycle API | ダッシュボード/wrangler r2 bucket lock add/API |
| 上限 | 1バケットあたり最大1,000ルール | 1バケットあたり最大1,000ルール |
| 同じオブジェクトに両方かかった場合 | Bucket Lockのルールが優先される | |
この最後の行が、実務でつまずきやすい落とし穴になる。同じオブジェクトにObject LifecycleとBucket Locksを重ねて設定した場合、Bucket Lockのルールがlifecycleルールよりも優先される。「90日で自動削除する設定にしたはずなのに、実は同じprefixにBucket Lockもかかっていて消えない」という状態が、表面上は気づきにくいまま起こりうる。逆に言えば、消してはいけないデータを確実に守れる仕組みでもある——優先順位を理解したうえで意図的に使えば、Bucket Locksは「Lifecycleルールの誤設定からデータを守る安全弁」にもなる。
なお、AWS S3のObject Lockには「Governance(管理者権限があれば解除できる)」「Compliance(誰も解除できない)」という2段階のモードがあるが、これに相当する権限段階がR2のBucket Locksにも存在するかどうかは、2026年8月時点の公式ドキュメントに明記が見当たらず、本稿では未確認として扱う。コンプライアンス上の強い保全要件を伴う用途で採用する場合は、この点を必ず公式ドキュメントの最新記載で確認してほしい。
Object LifecycleとBucket Locksは、「消す」と「守る」で役割が逆。同じオブジェクトに重ねて設定するときは、Bucket Lockが必ず勝つという優先順位を前提に設計する。
「データは国内に保管してほしい」と言われたら、どう答えるか?
R2のjurisdiction(保管地域)で選べるのはeuとfedrampの2つのみで、日本国内限定の指定は存在しない。技術設定だけでは答えられない要件として扱う。
個人情報や機微な音声データを扱うサービスでは、取引先や情シス審査から「データはどこの国に保管されているか」「国内に限定できるか」と聞かれる場面がある。R2にはjurisdictionという、バケット作成時にデータの保管地域を指定できる仕組みがある。ただし2026年8月時点で選べる値は「eu」と「fedramp」の2つのみで、日本国内限定を直接指定する選択肢はない。
| jurisdictionの値 | 何を指定するか | 制約 |
|---|---|---|
| 未指定(デフォルト) | Cloudflareのグローバルなネットワーク内で保管 | 特定地域への限定なし |
| eu | EU域内での保管 | S3互換エンドポイントが専用の形式に変わる |
| fedramp | FedRAMP対応リージョンでの保管 | 米国の政府機関向け要件を想定 |
実務上とりわけ重要なのが、jurisdictionはバケット作成後に変更できないという制約だ。運用が始まってから「やっぱり分けたい」と思っても、既存バケットの設定は変えられず、新しいバケットを作ってデータを移行するしかない。加えて、jurisdictionを指定すると、S3互換エンドポイントがhttps://{ACCOUNT_ID}.{JURISDICTION}.r2.cloudflarestorage.comという専用の形式に変わるため、前章で扱った署名付きURLの発行もこのエンドポイントに合わせて修正する必要がある。さらに、Logpush(ログの外部連携機能)はjurisdiction指定リソースと連携できないという制約も持つ。
つまり「国内保管」を要件にする相手には、jurisdictionという技術設定では応えられないという事実を、まず正直に伝える必要がある。そのうえで、実際にどう応えるか——保管場所以外の管理策(アクセス制御・暗号化・監査ログなど)で説明するのか、契約条項での合意にとどめるのか——は技術チームだけで決められる話ではなく、法務を交えて方針を決める必要がある。ここは本稿の範囲を超えるため、個別の契約判断は必ず法務・弁護士に確認してほしい。
削除依頼が来たとき、何をどこまで消せばよいのか?
R2上の元データだけでなく、バックアップ・ログ・キャッシュ・処理を委託したAIプロバイダまで削除の範囲に含めて設計しておく必要がある。
本人からの削除請求、契約終了にともなうデータ消去義務——理由はさまざまだが、「このデータを消してほしい」という依頼は、AIを扱うサービスを続けていれば必ず来る。このとき、R2のオブジェクトを消しただけで「対応完了」としてしまうと、実際には不十分なことが多い。
洗い出すべき経路は、大きく5つに整理できる。①R2本体のオブジェクト、②バックアップ・レプリケーション先、③アクセスログ・監査ログ、④CDNやアプリ側のキャッシュ、そして⑤文字起こしや要約のために送信した外部のAIプロバイダ側でのデータの扱いだ。特に⑤は見落とされやすい。自社のインフラの外に一時的にでもデータを渡している以上、削除依頼の範囲は自社のバケットの中だけでは完結しない。
ここで効いてくるのが、「渡した先」を後から追える形にしておくことだ。筆者が運営するAIインタビューサービスでは、処理者(実際にデータを処理する外部のAIプロバイダ、たとえばAnthropicやOpenAIなど)を同意文の中に明示し、同意そのものにバージョンを持たせて追跡している。新しい処理者にデータが渡るような機能を追加するときは、既定の状態をOFFにし、契約と同意文の更新が完了してから初めて有効化する。この順序を仕組みとして強制しておくと、削除依頼が来たときに「どこまで渡したか分からない」という事態を避けられる。
「消しました」と言えるのは、消した場所を全部言えるときだけだ。
最後に、本稿では触れられない範囲を明記しておく。個人情報保護法やGDPRといった法律が、具体的に何日以内の削除を義務づけるか、どこまでの範囲を「削除した」とみなせるかは、業種・データの性質・契約内容によって変わる法律解釈の話であり、本稿で断定はしない。運用ルールを確定させる前に、必ず法務・弁護士に確認してほしい。
削除依頼の対応範囲は、保存先を1つ増やすたびに広がる。新しい保存先・新しい処理者を追加するときは、それを消す方法もセットで決めておくと、あとから慌てて洗い出す作業をせずに済む。
よくある質問
最大7日間(604,800秒)です。最短は1秒から設定でき、配布に必要な時間に合わせて短く切るのが基本です。有効期限を過ぎたURLはアクセスできなくなり、リソース・操作・期限のいずれかを改ざんすると署名が一致しなくなり、403 SignatureDoesNotMatchで拒否されます。ただし、カスタムドメインを設定したバケットでは署名付きURLの発行自体ができない点に注意してください。S3互換エンドポイント({ACCOUNT_ID}.r2.cloudflarestorage.com)を使う必要があります。
目的が違うため、両方使うのが基本です。Object Lifecycleは一定期間が過ぎたら自動で削除する、または保存クラスを移すための仕組みで、通常の保持期間の運用を担います。Bucket Locksは指定期間、削除や上書きそのものを禁止するための仕組みで、監査証跡や契約上消してはいけないデータを守ります。同じオブジェクトに両方を設定した場合はBucket Lockのルールがlifecycleルールより優先されるため、「自動で消えるはずが消えない」という設計の落とし穴に注意してください。
2026年8月時点で、R2のjurisdiction(データの保管地域)として選べるのは「eu」と「fedramp」の2つのみで、日本国内限定を直接指定する仕組みはありません。国内保管を要件にする取引先がいる場合、技術設定だけでは応えられないため、契約や説明でどう答えるかを法務も交えて別途検討する必要があります。なお、jurisdictionはバケット作成後に変更できず、指定した場合はS3互換エンドポイントの形式やLogpushとの連携可否も変わる点を導入前に確認してください。
不十分な場合がほとんどです。R2上の元データを消しても、バックアップ、アクセスログ、CDNやアプリ側のキャッシュ、そして処理のために送信したAIプロバイダ側にデータが残っている可能性があります。削除依頼への対応範囲は保存先だけでなく処理の経路全体を洗い出したうえで設計する必要があり、法的にどこまでの削除義務があるかは弁護士・法務への確認が必須です。
