カウシェのバックエンドアーキテクチャを公開します
こんにちは、カウシェのバックエンドエンジニアの@ikeです。
ファーストリリースから2年弱が経過し、カウシェのバックエンドが今どのようになっているのか、特にインフラ周りを中心にご紹介します!
具体的には、以下のような点を記載しています。
ファーストリリース当時はどのような構成になっていたか
今、どうなっているのか
なぜ、そのようになったのか
ファーストリリース時
2020年9月は以下のような構成になっていました。開発言語はGoです。
Cloud Runでコンテナを動かし、認証にはFirebase、データベースにはFirestoreを用い…のようになっていました。
今みるとかなり一般的に見えますが、当時はCloud RunがGAになって半年強経ったくらいの時期感です。良い感じに攻めた最小構成になっているように思います。
ちなみに当時のバックエンドチームは2-3名(しかも全員副業!)と小規模で、CDNもLBもオブジェクトストレージもない、チーム構成もインフラ構成もまさに最小、という状態でした。
少し特殊なのは、外部サービスとしてShopifyを用いている部分がある、という点だと思います。
ShopifyはECサイトを簡易に構築できるSaaSで、BASEやSTORESに近いサービスです。当初は2ヶ月でリリースすることを目標にしており、EC周りの実装工数削減のために導入しました。
現在
上記の状態から2年の時を経て、現在は以下のような状態になっています。
CDN、LB、Spanner、認証系サービス、Lookerなどなど、当時と比べると全体的に利用技術が増えています。
最初は一つだけだったプロダクトも、以下の二つが追加されて全部で三つになっています。
内部管理画面
2021年前半に追加
カウシェ内部の人が運用時に利用(バナーやクーポンの入稿など)
事業者向け管理画面
2021年後半に追加
カウシェに商品を出品してくださる方々が利用(商品の入稿や、購入商品の確認など)
また図には書いてないですが、チームが2チームに増えました。それぞれのチームには4-5名のバックエンドエンジニアがいるような状態になっています(ただし正社員は両チーム合計して2-3名と、変わらず少数)。
以下では、当時と今で、構成において特に変わった点について記述していきます。
認証
当時はプロダクトがネイティブアプリしかなく、Firebaseでの認証ができれば十分な状態でした。
しかしプロダクトが増え、かつそれぞれのプロダクトの認証に求められる要件が異なっていたため、今では以下のように三つの認証サービスを利用しています。
内部管理画面ではIdentity-Aware Proxy(IAP)を用いています。IAPを用いると、Googleアカウント(Google Workspaceのアカウント)やGoogle Groupに対してIAMを付与することで、特定のGooleアカウントの場合のみGCP上リソースへの通信を許可する、などを簡単に実現できます。
内部管理画面の場合は利用者がカウシェ内部のメンバーのみで全員Googleアカウントを持っているため、IAPを用いて権限管理と認証を実現することにしました。
事業者向け管理画面ではIdentity Platformを用いています。Identity PlatformはFirebaseと大体同じようなことができますが、MFAなどより幅広い要件に対応できるのが特徴です。
事業者向け管理画面の場合、利用者はカウシェ内部のメンバーではなく、事業者の方々になります。事業者の方々はそれぞれ独自のメールアドレスを持っており、管理画面に任意のメールアドレスでログインできる必要がありました。メールリンクによる認証を行いたかったのと、将来的には別の方法やMFAなどの要件が求められる可能性があったので、Identity Platformを用いることにしました。
データベース
最初はFirestoreのみでしたが、現在ではSpannerも利用しています。Spannerは事業者向け管理画面で利用しています。
どういう経緯でSpannerを用いることになったかというと、話は事業者向け管理画面の開発をどのように進めるか議論した時に遡ります。
もともと1チーム体制で開発していたのですが、その時すでに人数が増えてきていたのと、かつ事業者向け管理画面はネイティブアプリ側とドメインが大きく異なっていました。そのため2チーム体制に変更してバックエンドのサービスも二つに分離して進める、という決定をしました(さらっと書きましたが、実現工数や運用工数含めたメリデメ等、結構議論をしました)。
その際に、サービス分離してチームの独立性を高めるならデータベースも分ける、という話をしました。
新サービスで用いるデータべースについて以下のような選択肢がありました。
当時の利用技術スタックと合わせて、Firestoreを新しいサービスでも採用する
他のデータベースを採用する
短期的な実現工数だけで判断すると前者が楽だったのですが、結果としては以下のような理由と、カウシェのバリューであるTry Firstの考えが後押しし、事業者向け管理画面ではSpannerを用いる、としました。
RDBでデータ整合性に強いマネージドデータベースをできれば使いたかった
Spannerの本番運用経験があり、ノウハウを持っている方がカウシェにいた
ちょうどその時期に、従来価格の10分の1のコストで利用開始できるSpannerのプランが発表された
バッチや非同期処理
最初の時点から以下のような非同期処理やバッチがありました。ただし数は多くなく、それぞれ1-2個程度でした。
Pub/Subによる非同期処理
XXしたらプッシュ通知を送る、など
Cloud Schedulerによる定期実行
XXを期限切れ状態に更新する、など
現在では非同期処理もバッチ処理も数が増えて、個数は当時の数倍程度になっています。
また新規のサービスとしてCloud Tasksを導入しました。外部サービスに対する非同期処理があり、その際にAPI呼び出しのrate-limit制約を満たすように処理を実現したい、などの要件が現れたためです。
Cloud TasksはPub/Subと同様に非同期処理を実現できるサービスですが、Pub/Subと比べて、処理をいつ実行するかや、実行頻度の制限をより細かく管理できる、という特徴があります。
CDN, LB, CI/CD, 分析周り
当時はCDNもLBもない状態でしたが、現在はFastly, Cloud Load Balancingが導入されています。 CI/CD周りではCloud Buildが一部導入されました。分析周りではData StudioからLookerへ利用サービスが変わっていったりしました。
今後について
現時点の課題と、今後どのような対応を取りそうか、について記述してみます。
一つ大きめの課題としては、サービス分離についての課題です。チーム数が増え、サービスが2つになるようサービス分離を進めましたが、構成が歪になっている部分があります。例えば一部の通信がLBを通っていない、リポジトリ構成がわかりにく、などです。これを改善しつつ、チーム数をより増やしていきたい状態であるため、チーム数増加に伴うサービスの増加にも対応しやすい状態にしていきたいです。
単一サービスだった状態から複数サービス構成に適宜変えて行きたい、という状況が差し迫っているのは比較的珍しい状況かつ、実行に当たっては判断力が求められるという、面白い課題なのではと思っています。
もう一つの大きめの課題は、Shopifyへの依存です。初期では開発工数の削減を目的として導入し、実際に大きく工数削減できました。しかし現状だと、Shopifyに依存しているが故に逆に時間がかかる要件などが出てきており、依存を徐々に減らす検討をしている状態です。
これの検討にはECの多数のロジック、具体的には、決済、検索、推薦、バリエーション(色、サイズなどのパターン)、注文や配送情報管理などを考慮する必要があり、特殊な要件や難しい要件が多数出てきます。こちらも課題としては取り組むやりがいのあるものだと思います。
その他、監視周りで外部サービスを導入して運用効率を上げたい、分析基盤を整えていきたい、など、全般的に改善していきたい部分はあります。
まとめ
この記事ではファーストリリース時と今の状態、また今に至った経緯について、インフラレイヤを中心に記述してみました。
ビジネスやチーム状況、要件や効率を考慮しつつ、新しい技術を適宜導入している様子や、ユニークな技術的課題があって面白い環境である、という点が伝われば良いなと思っています、、!
簡易に書いてしまい詳細を伝えきれていない部分もあるので、もっと聞いてみたい!などがあればぜひカジュアル面談などでお話しさせてください!
「世界一楽しいショッピング体験をつくる」メンバーを募集中
カウシェでは、共に「世界一楽しいショッピング体験をつくる」メンバーを募集しています!少しでも気になった方は、ぜひ下記よりエントリーいただければと思います。