Relay API設計:Cloudflare Workersでメール送信基盤を構築

1. なぜ外部メールプロバイダのAPIを使わなかったのか

メモをメールで送信するアプリを作るとき、最初に思い浮かぶのは大手メールプロバイダの送信APIです。しかし、個人開発者にとってGoogle OAuth審査のハードルは極めて高いものでした。

Google OAuth審査を通過していないアプリには、「このアプリはGoogleで確認されていません」という警告画面が表示されます。メモアプリにとって、この警告は致命的です。ユーザーは自分の考えや個人的な情報をメモとして送信します。その最初の体験で「検証されていません」と表示されたら、誰がこのアプリを信頼するでしょうか。

Google OAuth審査の申請プロセスは、個人開発者にとって険しい道のりです。プライバシーポリシーの準備、スコープの正当性説明、セキュリティ評価——大企業のチームならともかく、一人で開発しているアプリにとっては、メール送信という単一機能のために払うコストとしてはあまりにも大きすぎます。

必要だったのは、OAuth審査の複雑さなしに、ユーザーの信頼を損なわずメールを送信できるソリューションでした。その答えが、自前のRelay APIです。

2. Cloudflare Workers + Resend APIアーキテクチャ

Relay APIのアーキテクチャは、シンプルかつ堅牢です。iOSアプリからのリクエストを受け取り、メール送信サービスに中継する——それだけに特化した設計です。

iOS App → Relay API (Cloudflare Workers) → Resend API → Email Delivery

Cloudflare Workersは、世界中のエッジロケーションでTypeScriptコードを実行するサーバーレスプラットフォームです。Cloudflare の説明では、isolate という軽い実行環境でコードを動かすので、仮想マシン型のサーバーレスで起きるコールドスタートがありません。

Resend APIは、モダンなメール送信サービスです。SPF/DKIM/DMARCを設定しやすく、TypeScriptから簡単に呼び出せます。

費用の面では、Cloudflare Workersの無料プランは1日10万リクエストまで、Resendの無料プランは1日100通・月3,000通まで使えます(2026年10月時点の各社の料金ページ)。小さく始めて、送る量に合わせて有料のプランに移れる構成です。

3. メールアドレス検証(6桁コード方式)

Relay APIは、検証済みのメールアドレスにのみメモを送信します。これは悪用防止の最も基本的な防御層です。

メモ送信を開始する前に、送信先のメールアドレスを検証するフローが必要です。

  • ユーザーがアプリにメールアドレスを入力
  • Relay APIが6桁の検証コードをそのアドレスに送信
  • ユーザーが受信した6桁コードをアプリに入力
  • 検証完了。以降、そのメールアドレスへのメモ送信が許可される

この仕組みにより、他人のメールアドレスに無断でメモが送信されることを防ぎます。検証コードはそのアドレスの受信箱に届くので、受信箱を見られない人は、そのアドレスを送信先として確認できません。

検証はメールアドレスごとに一度だけ。一度検証が完了すれば、以降はコード入力なしでメモを送信し続けられます。

4. 多層レート制限の実装

メール送信APIの悪用を防ぐため、複数のレイヤーでレート制限を実装しています。

const RATE_LIMITS = {
  devicePerMinute: 30,
  devicePerDay: 200,
  ipPerHour: 120,
  globalPerDay: 300,
};
Device Level
デバイス単位の制限
1台のデバイスからの過剰な送信を防止。1分あたり30件、1日あたり200件の上限を設定。通常のメモ利用では到達しない閾値ですが、自動化による大量送信を止めます。
IP Level
IPアドレス単位の制限
同一ネットワークからの大量リクエストを制限。1時間あたり120件。複数デバイスを使った攻撃からもインフラを保護します。
Global
グローバル制限
インフラ全体の保護。1日あたり300件のグローバル上限を、最後の歯止めとして置いています(各上限の数値は設計時のもので、変更されることがあります)。
2026-09 追記
いまの上限
端末ごとの上限と全体の1日の上限は、2026年6月に撤去しました。いまの送信の上限は、IPアドレスごとの1時間あたりの上限です。

カウンターはCloudflare KVに保存され、各時間ウィンドウごとにリセットされます。通常の送信は通しつつ、不正な大量アクセスを抑えます。

5. 冪等性:同じメモを二重に送らないための設計

ネットワーク通信には不確実性がつきものです。送信ボタンを押してから応答が返るまでの間に、通信が途切れることがあります。アプリはタイムアウトと判断して再送信を試みますが、実は最初のリクエストはサーバーに届いていた——よくあるシナリオです。

この場面には、冪等性(idempotency)で備えます。

  • 各メモに一意のUUID(メッセージID)を付与
  • Relay APIは、そのメッセージIDを、メール送信サービス(Resend)への要求の冪等キー(Idempotency-Key)として渡す
  • Resendは同じキーを24時間覚えていて、同じ内容の要求がもう一度来たら、メールは送らずに前と同じ応答を返す
  • アプリには成功の応答が返る(2回目も1回目と同じ応答)

この設計により、ネットワークが不安定でリトライが起きても、24時間のうちは同じメモが重ねて送られません(Resendがキーを覚えている期間)。それより後の送り直しは見分けられないので、重複を止められるのはこの期間の中です。

6. エッジコンピューティングの利点

Cloudflare Workersをメール送信基盤に採用した最大の理由は、エッジコンピューティングの本質的な利点にあります。

Latency
世界中のエッジロケーション = 低レイテンシ
Cloudflareは世界300以上の都市に拠点を置いています。リクエストは利用者に近い拠点で処理されるので、遠くの1か所のサーバーまで往復するより通信の距離が短くなります(応答までの時間は、メール送信サービスの処理を含めて変わります)。
Cold Start
仮想マシン型のコールドスタートが無い
仮想マシンやコンテナで動くサーバーレスでは、しばらく使われなかったあとの最初の要求で、起動を待つこと(コールドスタート)があります。Cloudflare Workersはisolateで動くため、この待ちが起きない、とCloudflareは説明しています。
Operations
インフラ管理不要のオートスケーリング
サーバーの管理、キャパシティプランニング、スケーリング設定——これらすべてが不要です。リクエストが増えれば自動的にスケールし、アイドル時にはコストが発生しません。

メモアプリにとって、この組み合わせは扱いやすい選択でした。利用者に近い拠点で処理が始まり、サーバーの管理が要らず、小さな規模なら費用も抑えられます。それが、エッジコンピューティングでRelay APIを作った理由です。

この技術基盤の上に構築された「Obsidian連携シンプルメモ」を、ぜひお試しください。

App Storeでダウンロード

参考文献