Cloudflare R2で、ニアリアルタイムなAPIを劇的に安くする

# この記事について

#### 結論を 1 行で

Cloudflare R2 で API Gatewayを置き換えると、 Web サービスの開発が劇的に安くなるかもしれない

#### 対象読者

- AWS、特に S3 を知っている、または聞いたことがある
- 個人開発～やや小規模な Web・IoT サービスを開発している

#### 記事の内容を簡単に説明すると

- 2022 年 9 月に『AWS S3 互換のサービス』として Cloudflare の R2 が一般公開された
  - できること＆使い方は S3 とほぼ同じ
  - ただし料金体系が異なる

![img-r2-s3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/ddd48fbb-754e-4cf1-41f0-b59f676b6b30.png)

- R2 は S3 互換だが、S3 らしい利用方法をしても安くならない
  - ストレージの料金設定が 1 つしかなく、ログの保管用途だと高い
  - S3 と同じ用途で使うなら、連携の良さを捨ててまで乗り換えるメリットはない

![img-r2-s3 copy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/48111e64-0ac1-2ff2-955d-01d11f838b4a.png)

- 一方で、S3 らしくないことをさせるのなら衝撃的に安い
  - 書き込みの無料利用枠が S3 の約 500 倍
  - 読み込みも月間 1000 万回まで無料

![img-r2-s3 copy 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/98a26a0e-8dd7-6768-4b6f-270b477d02da.png)


- データレイクとしてではなく、ニアリアルタイムな API として見るのがオススメ

# 記事

## ニアリアルタイムな API

![api-realtime.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/dc939622-c154-6bc2-81b9-5076bae08e11.png)

### 処理の流れと料金の発生タイミング

数分のラグが許される読み取り処理なら、以下のような構成の API を作ることができます

![img-b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/cdf31de1-cc9c-7a13-ba66-7b3c062ce01f.png)

身近なところだと、気象庁のナウキャストの API が似た形式になっています

10 箇所のどこかの地点の情報を返す API を作るなら、総当たりで 10 箇所分の JSON を作ってしまおう、のアプローチです

リクエストのたびに発生する処理がないので閲覧が早いこと、急に閲覧するユーザーが増えても S3 の読み込みにかかる料金だけで済むことがメリットです

### AWS で構築するのにかかる料金

ニアリアルタイムな API と、それを配信する Web サイトの構築にかかる料金は以下の通りです

- 定期処理（Lambda）の実行
- JSON ファイルの配信
- HTML の静的ファイルの配信

#### Lambda の料金はかなり安い

Lambda の無料利用枠は以下のようになっています
※メモリ 1GB で動かす場合

|                | Lambda（東京リージョン） |
| :------------- | :----------------------- |
| リクエスト回数 | 100 万回/月まで          |
| 処理時間       | 40 万秒まで              |

月 40 万秒とかなり余裕があります。『メモリ 1GB、1 回あたり平均 20 秒』の複雑な処理だとしても、毎日 3 分に 1 回のペースで動かしても無料枠で収まります

#### S3 は書き込みの無料枠がやや狭い

S3 の無料利用枠は以下のようになっています

|                        | S3（東京リージョン）                    |
| :--------------------- | :-------------------------------------- |
| データ転送の無料分     | 100GB/月まで                            |
| データ保管の無料利用分 | 5GB まで無料                            |
| 書き込みの無料利用分   | 2 千回/月まで<br />※1 時間あたり約 3 回 |
| 読み込みの無料利用分   | 20 千回/月まで                          |

無料枠は月間 2,000 回の書き込みですから、20 分ごとに 1 つのファイルを更新するだけで足が出ます  
読み込みも月間 20,000 回と、ほんの少しアクセスが集中するだけで不安になる無料枠です

![img-r2-s3 copy 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/77b1107f-426e-3de4-0b17-8af4ba3a8888.png)

HTML の静的ファイルも S3 で配信するのなら、無料枠はさらに狭くなります

また、Lambdaの無料利用枠は無期限ですが、S3の無料枠はアカウント登録から12か月の間だけ存在します

### Cloudflare で構築する場合

Cloudflare の料金体系は、ニアリアルタイムな API の構築が得意です

![img-r2-s3 copy 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/db570253-2824-7033-256e-cf2316211b6f.png)

#### R2 は書き込みと読み込みの無料枠が大きい

S3 と比較した R2 の無料枠は以下のようになります

|                        | R2                                              | S3（東京リージョン）                    |
| :--------------------- | :---------------------------------------------- | :-------------------------------------- |
|無料枠の条件|無期限|アカウント登録から12カ月間|
| データ転送の無料分     | 無料                                            | 100GB/月まで                            |
| データ保管の無料利用分 | 10GB まで無料                                   | 5GB まで無料                            |
| 書き込みの無料利用分   | 1,000 千回/月まで<br />※1 時間あたり約 1,388 回 | 2 千回/月まで<br />※1 時間あたり約 3 回 |
| 読み込みの無料利用分   | 10,000 千回/月まで                              | 20 千回/月まで                          |

R2 の書き込み無料枠は S3 の 500 倍あります  
1 分ごとに 20 ファイルずつ更新しても平然と収まります

また、12か月の制限もありません

#### 静的ファイルを配信する Cloudflare Pages

R2 と同じ Cloudflare のサービスに、静的な HTML を無料で配信できる Cloudflare Pages があります

|                                  | Cloudflare Pages                      | Github Pages  |
| :------------------------------- | :------------------------------------ | :------------ |
| 公開方法                         | git のファイルを Web サイトとして公開 | 同左          |
| 料金                             | 無料                                  | 無料          |
| 公開するファイルサイズ合計の上限 | 2000 ファイルまで                     | 1GB まで      |
| 1 つのファイルサイズの上限       | 25MB まで                             | 50MB まで     |
| アクセス制限                     | 制限なし                              | 月 100GB まで |

Cloudflare Pages は、類似サービスである Github Pages と比べても優秀です。月にどれだけ多くのアクセスがあっても上限がないことが特徴です。API は月 1000 万回まで無料で利用できる R2 を利用して、静的なHTMLファイルは無料の Cloudflare Pages で配信することで、運営にかかる費用を無料枠の範囲で抑えることができます

DDoS 攻撃や不意のスパイクを心配する必要もなく、枕を高くして眠れます

## R2 の導入方法

R2 は S3 互換の API を持っており、簡単に始めることができます

- Cloudflare R2  
  https://www.cloudflare.com/ja-jp/products/r2/

#### バケットの作成

まず R2 のコンソールを開いて、バケットを作成します。① にある、「バケットを作成する」をクリックします

![r2-toppage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/1df9ce7a-aa66-ef2a-7f72-f7b918b62652.png)

バケット名を入力すると、バケットが作成されます  
※S3 とは違って、バケットにリージョンの指定はありません。また、他のアカウントが作っているバケット名と重複する名前を使うことができます

![create-bucket.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/f700dfa8-a013-e02b-f5de-02a710a3cd4b.png)

バケットを作ったら、② にあった「R2 API トークンの管理」をクリックします

![create-token.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/d2e5c2cf-38bb-8ad5-0b86-efc62b9c83ea.png)

ファイルのアップロードが必要なら「編集」の権限をつけます  
TTL でトークンの有効期限を指定して、API キー、シークレットアクセスキーをコピーします  
特定のバケット／特定のファイルだけに権限をつけることはできず、フルアクセスの権限が設定されますので、API キーの取り扱いには注意が必要です

![created-token.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/f15da9d2-e828-6a77-3fb0-3b7d418729dd.png)

TTL を延長しても API キーとシークレットアクセスキーはそのまま使えるため、期限が切れそうになったら R2 のコンソールで更新するだけで OK です

![public-setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/1e30d70a-c630-b3cc-be38-03d7fa51b57e.png)

作ったバケットは、クリックひとつでインターネットに公開することができます。CORS の設定をつけることも可能です

#### アップロードするソースコード

Lambda から R2 へのアップロードは、S3 へのアップロードと同じ方法で実施できます

Lambda の環境変数には、あらかじめ以下のパラメータを設定しておきます

| キー             | 詳細                                         |
| :--------------- | :------------------------------------------- |
| R2_ACCESS_KEY_ID | トークンで発行した API キー                  |
| R2_SECRET_KEY    | トークンで発行したシークレットキー           |
| R2_ENDPOINT      | バケットの詳細画面にあるエンドポイントの URL |
| R2_BUCKET_NAME   | バケット名                                   |

```python
# importするライブラリ
import json
from os import environ
import boto3
import io

# アップロードするファイル名
upload_file_name = "filename.json"
# アップロードするファイルデータ
json_data = {
    ...
}

# セッションを作成する
r2_session = boto3.Session(
    region_name="auto",
    aws_access_key_id=environ.get("R2_ACCESS_KEY_ID", ""),
    aws_secret_access_key=environ.get("R2_SECRET_KEY", ""),
)
# バケットに接続する
r2_client = r2_session.resource("s3", endpoint_url=environ.get("R2_ENDPOINT", ""))
r2_bucket = r2_client.Bucket(environ.get("R2_BUCKET_NAME"))

# データを書き込む
with io.BytesIO(json.dumps(json_data).encode("utf-8")) as fp:
    r2_bucket.upload_fileobj(fp, upload_file_name)
```

S3 と同じ boto3 で操作できますから、Lambda で利用するのに特別なライブラリは不要です  
アップロードやダウンロード、署名付き URL の発行、マルチパートアップロードなどもできます

#### 実際に動いているところ

1 時間に 7 回 R2 のファイルを更新する Lambda を作成して、1 日動かしたところです  
R2 のメトリクス画面で、アクセスされた回数を確認することができます

![graph-image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/c1c83671-6874-bde8-015e-f3555618f1e8.png)

クラス A（緑の線）が書き込み、クラス B（赤い線）が読み込みになります  
緑の線は 7 で水平になっていますから、想定通りの回数のリクエストが発生していることが確認できます

![response-time.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/d63fac6e-ecb2-2a87-6189-1e9e6d713522.png)

Web アプリから 1KB の JSON を Ajax で要求したとき、レスポンスが返るまでの時間は 0.3 秒でした

![billing-r2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/a14e038b-9ec3-e756-46b9-dbcd75782c26.png)

請求画面はこのようになっています。明細はサービス単位で出てきます

![billing-s3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/fd85c0d1-d5ec-16c7-eb7e-a4cf193ce479.png)

こちらは S3 の明細です。月 5000 回の書き込みで 0.02 ドル、この部分が R2 への置き換えで無料になります

目的ごとの料金を細かく出してくれますので、R2 に比べると S3 のほうが読みやすい明細です

## R2、なんで話題にならないの？

2023/01/06 の時点で、Qiita で R2 のタグが付いた記事は 8 件しかありません  
2022 年の 9 月に一般公開されたばかりではありますが、それを差し引いても盛り上がりはいまひとつです

デメリットや、R2 の微妙な部分について説明します

### 無料枠を超えた部分の料金について

R2 と S3 について、無料枠を超える部分の料金を比較してみます

|                  | R2                      | S3（東京リージョン）                      |
| :--------------- | :---------------------- | :---------------------------------------- |
| データ転送料金   | 無料                    | 0.114 ドル/GB ごと                        |
| 書き込みの料金   | 4.5 ドル /100 万回ごと  | 4.7 ドル /100 万回ごと                    |
| 読み込み料金     | 0.36 ドル /100 万回ごと | 0.37 ドル /100 万回ごと                   |
| データの保管料金 | 0.015 ドル / GB ごと    | 標準ストレージ：0.025 ドル/ GB ごと       |
|                  |                         | 1 zone：0.011 ドル/ GB ごと               |
|                  |                         | 低頻度アクセス：0.0138 ドル/ GB ごと      |
|                  |                         | Glacier：0.0045 ドル/ GB ごと             |
|                  |                         | Glacier Deep Archive：0.002 ドル/ GB ごと |

無料枠を超えてしまうと、書き込みと読み込みの料金に差はありません

データを保管する実際のケースにあてはめて、1TB の 1 カ月あたりの保管料金を比較してみます

| ケース                                         | R2         | S3（東京リージョン）                 |
| :--------------------------------------------- | :--------- | :----------------------------------- |
| バックアップが不要なログデータ                 | <font color="red">15 ドル/月</font> | <font color="green">11 ドル/月</font>（One Zone IA を使用）     |
| アクセスの少ないログデータ                     | <font color="red">15 ドル/月</font> | <font color="green">13.8 ドル/月</font>（低頻度アクセスを使用） |
| 滅多に見ないログデータ                         | <font color="red">15 ドル/月</font> | <font color="green">2 ドル/月</font>（Deep Archive を使用）     |
| ミリ秒アクセスが必要で、消えてはいけないデータ | <font color="green">15 ドル/月</font> | <font color="red">25 ドル/月</font>（標準を使用）             |

S3 には「取り出しに時間がかかるかわりに低料金」「データをバックアップしない代わりに低料金」など、性能とのトレードオフで料金を下げる方法が用意されています。利用量に応じた値下げもあります

R2 は明朗会計なのですが、明朗になったぶん値引きがありません

### エグレスコストのインパクトについて

また、S3 にはエグレスコストと呼ばれる転送料金があるのですが、エグレスコストは全ての転送にかかるわけではありません

- 有料になる転送料金
  - S3 からインターネットに直接（※CloudFront を挟まずに）ダウンロードする
  - S3 から他の AWS サービスに連携する
  - S3 から他のリージョンの S3 に転送
- 料金がかからない転送
  - インターネットから S3 にアップロードする
  - CloudFront を挟んでインターネットにアウトプットする
  - 月 100GB に満たないインターネットへの転送

![img-r2-s3 copy 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233180/9e09a4ca-c812-524b-21e8-a459581d7a14.png)

### セキュリティのネックについて

R2 のアクセスキーの権限が強すぎる上に、管理もネックになります

R2 のアクセスキーには「フルアクセス」「リードオンリー」のどちらかしかありません。IP アドレスで制限をかけることはできるのですが、Lambda とは相性の良くないセキュリティ方法になります。Lambdaは割り振られるIPアドレスが固定されません

S3 に比べるとリスクが大きく、保管を考えると、コスト的なメリットも大きくない印象です。セキュリティのために、アクセスキーを SecretManager で管理するとしたら、月 0.4 ドルの使用量がかかります。TTLの更新のために保守作業も発生します

S3からの置き換えで無条件に料金が下がるところは多くないのではないかと思います

## まとめと結論

R2 を APIGateway から置き換えるつもりで使うと間違いなく安くなります  
月に 100 万単位のアクセスがあるサイトも、無料枠だけで運営できるだろうと思います

ただ、認証情報の扱いづらさが負担になるので、置き換えには慎重さが必要です  
R2 を S3 から置き換えるつもりで使うなら、安くなるかどうかは微妙です

### 参考サイト

- Cloudflare R2 の一般提供を開始しました  
  https://blog.cloudflare.com/ja-jp/r2-ga-ja-jp/