ROBOT PAYMENT Engineers Blog

株式会社ROBOT PAYMENTのテックブログです

サーバーレスな非同期メール配信サービスを作ったら組織の未来が見えた話

こんにちは、SREチームの田中(@j_untanaka)です。
先日、請求管理ロボのメール送信処理を改善するための内部的なサービスをリリースしました。
今回はその技術的な側面と、開発を通して得た所感などを書いてみたいと思います。

目次

課題だったこと

請求管理ロボではメール送信にSendGridを使用しています。
サービスの性質上、請求書送付やユーザへのお知らせ通知等大量にメール送信する場面があるのですが、多くの機能においてメール送信(SendGridへの送信リクエスト)を1件ずつ直列に実行していたことにより、利用者の増加にともないパフォーマンス低下を招いている状況でした。
APMでボトルネックを確認すると、やはり外部サービスへのリクエストとなっている分SendGridからのレスポンス待ちで多くの時間を使っていました。
そのためメール送信機能を請求管理ロボ本体から切り出し、送信リクエストを受け付けたらいい感じでさばいてくれるサービスを作ることにしました。

機能

  • メール非同期送信
  • バウンスメールの記録および送信者への通知

技術スタック、システム構成

いわゆるサーバーレスアプリケーションの体裁をとっていて、以下のような技術スタックとなっています。

Programming language: JavaScript (Node.js)
Infrastructure: AWS (SQS, Lambda, API Gateway, DynamoDB, Kinesis Data Firehose, S3)
Test Framework: Jest
Provisioning: AWS SAM
CI/CD: GitHub Actions

f:id:j-u:20210426220754p:plain
システム概要

SQSを経由し非同期でSendGridへリクエスト送信するのが基本的な流れとなります。
何らかの理由でSendGridへのリクエストが失敗した場合、DLQを経由して再送信を試みるようになっています。
SendGridからのメール配信結果はWebhookで受信し、バウンスや宛先不備により不達となった場合はその旨を利用企業にメール通知、合わせて不達メールのログをS3に保存して調査に利用しています。
SendGridから同一メッセージIDのWebhookを受信した場合に重複排除する目的で一度DynamoDBにログレコードを登録しています。
現時点ではDynamoDBのレコードはTTL設定して一定期間経過したら削除するようにしています。

運用系にも少し触れておくと、今回初めてGitHub Actionsを実践投入してみました。
今までCI/CDまわりの機能にはCodeBuild等AWSのサービスを利用することが多かったのですが、比較すると当然といえば当然ですがいわゆるGitOps的なものを実装するのが非常に楽です。ワークフローを定義するyamlファイルをリポジトリの所定の場所に置いておけばすんなり動いてくれます。
またactというサードパーティツールが非常に便利で、GitHub Actionsと同等のイメージでワークフローをローカル実行できます。開発端末にDockerとactだけインストールしておけば環境構築で消耗することなくテストを実行したりできます。

github.com

反面、AWS SAMを使う都合上AWSリソースを強めの権限で操作できるCredentialをGitHub側に登録する必要があるため、AWS内でIAMロールのみで権限制御するのと比べると気持ち的に少し気になります。ベストプラクティスにそって、最小限の権限に絞ったIAMロールへAssume RoleできるIAMユーザをGitHub側へ登録するようにしています。

よかったこと

技術選定

請求管理ロボはリリースから7年近く経過し、おかげさまでビジネスとしては順調に推移しているものの、積み重ねた年月の分だけ仕様も大きく複雑なシステムとなってきています。またアーキテクチャの古さや溜まりがちな負債の影響もあり技術的なチャレンジがしづらい状況となっていました。
そんな中で今回はメール送信というビジネスロジックから切り離しやすい領域だったこともあり、本体の実装から切り離して普段とは違う技術選定で新規開発することができました。

開発期間

ざっくりプロトタイピング1~2週間、ファーストリリースまで1ヶ月、追加開発および運用にのせるまでトータル3ヶ月程度と、普段の我々の開発速度と比較するとスピード感のある動きができました。
仕様が小さくアウトプットが明確だったこと、AWS SAMがいい感じでレールを敷いてくれたことなどが良い結果につながったと思います。

メンバーのモチベーション

先述の技術選定に加え、今回請求管理ロボ開発メンバーとSREメンバーから数名が超党派でチームを結成して開発を行いました。普段と違うことを違うメンバーでやって刺激になったように感じます。
また普段インフラ寄りの領域をあまりさわらないメンバーがAWSちょっと分かるようになってきた!とドヤったり、逆にインフラ寄りのメンバーがばりばりユニットテスト書いてオラついたりする様子も見受けられ、なかなかテックで良い雰囲気の現場となりました(全員リモートですが)。

この経験を生かして

ここまでご紹介してきたことの多くは、いわゆるマイクロサービスアーキテクチャの利点と一致するように思います。
先述の通り請求管理ロボは大きなレガシーシステムとなりつつあります。そろそろ大規模なリプレイスが必要ではないかという話は以前からあがっているのですが、技術的な難易度や人的リソースの都合、新機能追加との優先度の兼ね合いなどが問題となりなかなか前進しないのが実状です。
しかし今回のようにいい感じのサイズに切り出せる機能を見つけては外に出して、少しずつ本体を身軽にしていくことはできると思っています。
イキって全体リプレースだ!と構えず、地道に少しずつ進めていくことが現実的であると今回のプロジェクトを通して示すことができたと考えています。

また、目先を変えて普段と違うことをやるメリットも強く感じました。
我々の課題として先述のレガシーシステム問題に加え、プロダクトごとに開発組織が縦割り気味な点があります。つまり同じメンバーと同じシステムと向き合う時間が必然的に長くなります。これには一つのシステムへの理解を深められるというメリットもありますが、マンネリ化するというデメリットもあると思います。

ふまえて、例えば機能によってはプロダクト横断で使えるサービスを切り出すことができれば、複数プロダクトメンバーで開発し横展開するような動きが考えられます。今回のメール送信などは比較的横展開しやすい機能と言えます。

切り出せる小さな機能を探す → 部署を超えて人が集まりチームを結成する → 作る → 解散(運用はする) → 振り出しへ戻る

といったサイクルを繰り返すことで、いろいろな人といろいろな技術/開発手法/ツール/etc.にチャレンジしながら縦割り組織を変えていく。結果つよつよ技術者集団ができあがる。というと話が飛躍しているかもしれませんが、あながち夢物語でもないように思います。

We are hiring!!

絶賛仲間募集中です。

hrmos.co