エンジニアリング · 2026年9月21日
トランザクションメール移行のプレイブック
可観測性を失わずにトランザクションメールのプロバイダーを移行するには、段階的なアプローチが必要です。二重送信、イベントの対応付け、DNSの段階的な切り替えを組み合わせます。
移行の核心的な課題
可観測性を失わずにトランザクションメールを移行するには、送信のトリガーとプロバイダーの実装を切り離す必要があります。戦略としては、二重送信(シャドー送信)とイベントの対応付けを可能にするプロバイダー抽象化レイヤーを実装します。Webhookで配信イベントの追跡を続けながら、トラフィックのごく一部を新しいプロバイダーに振り向けることで、メインの経路を切り替える前に、新しいプロバイダーがメールを受け付けること、そして可観測性のパイプラインが結果を捕捉できることを検証できます。
移行が行われる理由
移行の動機の多くは、コスト、開発者体験、コンプライアンスです。たとえば、プロバイダー間のコスト差は大きなものです。Amazon SESの料金によると、à-la-carteでの送信は1,000通あたり0.10 USDです。一方、Postmarkの料金は月額15 USDで10,000通からで、超過分は1,000通あたり1.80〜1.20 USDです。50,000通の送信は、SESのà-la-carteならおよそ5 USD、Postmarkのプランなら約66 USDです。
ほかにも、EU限定でプライバシーに配慮した最小限のテレメトリーへの移行や、エージェント対応の強化(MCPサーバーのサポートなど)の必要性が動機になります。理由が何であれ、リスクは同じです。移行期間中に配信パイプラインに死角が生じることです。
フェーズ1:抽象化レイヤー
アプリケーションがビジネスロジックの中でプロバイダーのSDKを直接呼び出していると、そのプロバイダーにロックインされます。リクエストとレスポンスを標準化するラッパーが必要です。
統一ペイロード
プロバイダーに依存しない内部スキーマを定義します。これにより、基盤のAPIがtoを配列として受け取るのか単一の文字列として受け取るのかを、アプリケーションが気にする必要がなくなります。
{
"message_id": "msg_12345",
"recipient": "user@example.com",
"template_id": "welcome_email",
"variables": {
"name": "Alex"
},
"idempotency_key": "unique_request_id_789"
}
AIエージェントや自動化されたワークフローを扱う場合、メールを外部への副作用として扱うことが不可欠です。冪等キーを使い、エージェントのループが再試行されても、同じトランザクションメールが1人のユーザーに5回送信されないようにしてください。
フェーズ2:DNSとIDの設定
1通でもメールを送る前に、送信者としてのIDを確立する必要があります。DNSの反映の遅れや設定ミスにより、多くの移行はここで失敗します。
- ドメインを検証する:新しいプロバイダーのDKIMレコードとSPFレコードを追加します。SendHQのメールDNSチェッカーのようなツールを使って、レコードが公開され、正しい形式であることを確認してください。
- レコードを理解する:SPF(サーバーを認可する)とDKIM(メッセージに署名する)の違いを理解しておいてください。移行中に複数のプロバイダーを使う場合、SPFレコードには両方を含める必要があります。
- DMARCのアライメント:アライメントがわずかにずれていた場合のハードバウンスを避けるため、移行の初期段階ではDMARCポリシーを
p=noneに設定してください。設定手順の詳細は、SendHQのDKIM、SPF、DMARCガイドを参照してください。
フェーズ3:シャドー送信(二重送信)
一気に切り替えてはいけません。代わりに、メインのプロバイダーに送信しつつ、複製(またはサンプリングした一定割合)を非同期で新しいプロバイダーに送信するルーティングロジックを実装します。
実装ロジック
async function sendEmail(payload) {
// Primary send (Current Provider)
const primaryResult = await primaryProvider.send(payload);
// Shadow send (New Provider) - do not await or block the main thread
if (Math.random() < 0.1) { // 10% sample
newProvider.send(payload).catch(err =>
console.error("Shadow send failed", err)
);
}
return primaryResult;
}
このフェーズでテストするのはプロバイダーによる受け付けです。これは、プロバイダーが「はい、このメッセージを引き受けます」と応答する時点を指します。これは配信(メッセージが受信側サーバーに届くこと)や受信トレイへの到達(メッセージが迷惑メールフォルダを避けること)とは別物です。
フェーズ4:可観測性とイベントの対応付け
可観測性とは、メッセージをsentからdeliveredまたはbouncedまで追跡できることです。Webhookのスキーマはプロバイダーごとに異なります。
イベントの対応付け
イベントを正規化して社内のデータベースに取り込むための対応表を作成します。
内部イベント | Amazon SES | Resend | Postmark | SendHQ
sent | Send | sent | Sent | sent
delivered | Delivery | delivered | Delivered | delivered
bounced | Bounce | bounced | Bounced | bounced
complaint | Complaint | complained | Complaint | complaint
Webhookペイロードの処理
Webhookリスナーは汎用的にしておくべきです。新しいプロバイダーからペイロードを受け取った場合は、分析エンジンに渡す前に変換処理を通します。
function transformWebhook(provider, payload) {
switch(provider) {
case 'resend':
return { event: payload.data.delivered ? 'delivered' : 'failed', id: payload.data.id };
case 'sendhq':
return { event: payload.event, id: payload.message_id };
default:
throw new Error("Unknown provider");
}
}
フェーズ5:段階的な切り替え
新しいプロバイダーがメールを受け付けること、そしてWebhookがイベントを正しく対応付けていることを確認できたら、重み付けによる振り分けに移ります。
- トラフィックの1%:すべてのトランザクションメールの1%を新しいプロバイダーに振り向けます。バウンス率を監視します。
- トラフィックの10%:負荷を増やします。レート制限を確認します。たとえば、Resendの無料プランは1日100通までに制限されており、テスト中のボトルネックになることがあります。
- トラフィックの50%:安定性のテストです。レイテンシーが許容範囲に収まっていることを確認します。
- トラフィックの100%:最終的な切り替えです。
移行時によくある失敗のトラブルシューティング
「サイレントドロップ」
プロバイダーの中には、メールを受け付けた(202 Accepted)ものの、コンテンツフィルターや未検証の送信者IDのために内部で破棄してしまうものがあります。シャドー送信のフェーズが欠かせないのはこのためです。sentイベントが多いのにdeliveredイベントが少ない場合、問題はAPIではなく配信にあります。
レート制限の急な発動
バースト時の上限はプロバイダーによって異なります。Mailgunの料金とSendGridの料金(現在は無料プランが60日間のトライアル)では、スループットのクォータが異なることがよくあります。上限の高いアカウントから新しいアカウントに移行すると、スロットリングされる可能性があります。急増を平準化するには、キュー(RabbitMQやSQSなど)を導入してください。
冪等性の失敗
プロバイダーを切り替える際に、誤ってバッチの再試行を引き起こすことがあります。AIエージェントにメールを送信させている場合は、エージェントが一意のリクエストIDを渡すようにしてください。エージェントがMCPサーバーを使ってメールAPIとやり取りしている場合、APIは24時間以内の重複したidempotency_keyの値を拒否すべきです。
移行チェックリスト
- 抽象化レイヤーが実装されています(プロバイダー非依存のペイロード)。
- 新しいプロバイダー用のDNSレコード(SPF、DKIM)が追加されています。
- sendhq.cc/tools/email-dns-checkerでDNSを検証しました。
- 新しいプロバイダースキーマを処理できるようWebhookリスナーが更新されています。
- イベントマッピング表が完成しています(Sent、Delivered、Bounced、Complaint)。
- シャドー送信が1%〜10%で有効になっています。
- エージェント主導の送信に対する冪等キーが検証されています。
- 段階的なランプアップ(1%、10%、50%、100%)。
- 100%で7日間安定稼働した後に、旧プロバイダーのAPIキーを失効させます。
プロバイダー選びについての結び
プロバイダー選びは、コストと開発スピードのトレードオフです。とにかく最低のコストを求めるなら、à-la-carteで1,000通あたり0.10 USDのAmazon SESに勝るものはなかなかありません。ただし、2026年7月21日以降、新しい料金プラン(Essentialsは0.16 USD、Proは0.22 USD)によって異なるコスト構造が導入されています。エージェント対応が組み込まれ、EU限定でプライバシーに配慮した最小限のテレメトリーを備えたモダンなAPIが必要なら、SendHQが効率的な代替手段になります。
どのプロバイダーを選ぶにしても、目標はエンジニアリングチームを特定ベンダーのSDKに縛り付けないことです。メールを標準化された副作用として扱うことで、リスクの高い移行を、日常的な設定変更に変えられます。
信頼性の高いメールワークフローの構築について詳しくは、https://sendhq.cc をご覧ください。