生産性を最大化するシリコンバレースタイルの Tech Stack
NutmegのVPoEを務める柳吾朗と申します。
日は、Nutmegの構築に使われているTech Stackについてお話ししたいと思います。
約5年前から開発を開始していますが、現在においても古さを感じさせない作りになっていると思いますが、皆さんの感想もお聞かせ願いたいです。
Nutmeg とは
Nutmeg は 観光DX向けバーティカルSaaS です。
オンライン予約の獲得から予約の管理、現場管理まで1つのプラットフォームで実現できます。
Nutmeg の Tech Stack
Nutmeg は元々 Uber や Microsoft で働いていたエンジニアを中心に、シリコンバレーで開発がスタートしました。当時の両社で使われていた技術の中から、Nutmeg のドメインにあったものが選定されています。
インフラ
AWS を使っています。
GCPよりもAWSの方が先行してサービスを開始しており、選定する時点で、クラウドとしてより安定している、という理由で選択しました。
BigQuery など、AWS では代替機能がない、もしくは弱い部分については、GCP を利用しています。
少ない人数で開発・運用が回せるように、できるだけフルマネージドのサービスを利用するようにしています。
データベース
DynamoDB を利用しています。
アクティビティのデータは正規化すると複雑な構造になり、拡張が難しくなるので、あえて NoSQL を選択しています。
「新しい機能を追加する度に ALTER TABLE」をする必要が無く、Schemaはコードで管理できるので、効率的です。
Schema は protobuf を使って定義しており、運用で backword compatibility を担保しています。
DynamoDB はスケーラビリティにも優れているので、現時点においてパフォーマンス上のボトルネックがデータベースになったことはありません。
フルマネージドな上に、他のサービスとの連携も優れているのもうれしいです。
検索
OpenSearch(ElasticSearch)を利用しています。
DynamoDB は検索があまり得意ではないので、複雑な検索は OpenSearch を使って実現しています。
DynamoDB の item 更新にフックされたイベントで、OpenSearch を更新しています。
頻繁に更新されるビジネスロジックから分離させているので、コードがシンプルにできます。
バックエンド
Golang を使って実装しています。
フレームワークは使用しておりません。
Golang は、オブジェクト指向の概念が他の言語と若干異なりますが、ここさえ乗り切れば比較的短時間で学習でき、高速で安定したサービスが構築できるので、助かっています。
個人的な感想ですが、 Java と比較しても運用が楽です。
Java では、効率的にGCができるように、JVM の起動パラメターを調整する必要があり、実装以外の部分でも時間がとられました。Golang の GC は優秀なので、今のところ手放し運転です。
バックエンドが提供する API は gRPC を使っています。現在バックエンドで動くサービスは1つですが、将来、他のサービスが作られたときに、高速に通信できるように作っています。
BFF(Backend for frontend)
TypeScript で実装しています。
バックエンドと gRPC で通信し、外部向けに REST API を提供します。
BFF はできるだけビジネスロジックは持たず、requestパラメーターのバリデーションや、APIへのアクセス権限管理をしています。
フロントエンド
TypeScript + Next.js で作られています。(管理画面は Pure React.js です)
BFF を介して取得できる API 応答を使ってUIを提供します。一部 SSR を利用し、高速化と SEO 対策を行っています。
Vercl も利用しています。Next.jsとの親和性が高く、運用コストを抑えることができます。
以上、ざっくりと Tech Stack を紹介してみました。細かいものはまだまだありますが、それらは今後触れることがあったら紹介したいと思っています。
一問一答
この章では、SaaS を作っている同業者さんと話したときに話題になる Tips について、一問一答形式で答えてみたいと思います。
マイクロサービスではないのですか?
マイクロサービスではありません。
マイクロサービスを導入する明確な理由が無かったからです。ただ、この先、バーティカルSaaSを展開する上で、必要になれば採用します。
各レイヤーに担当者はいるの?
いません。
現時点において、インフラ担当、UI 担当などの、役割はありません。
新機能の実装を任されたエンジニアは、それを実現するのに必要な事は基本的にすべて担当します。もちろんその過程で、必要な議論はチームで実施します。
私は簡単な設計書を作って、チームに共有し、フィードバックをもらうようにしています。
コードオーナーはいるの?
いません。
全体像を把握しているのは CTO の Andrew なので、基本彼がオーナーシップを持っています。
他のメンバーが実装している部分は、実装者が適宜フォローします。
Review はしている?
しています。
Nutmegはトランクベース開発を採用しており、1日に何回も main branch に commit が発生します。
そのすべてを review していると、reviewer の時間がとられてしまうので、重要な commit の時に mention して review を依頼しています。
デプロイはどうしている?
基本的にマニュアルで実施しています。
現在のところCI/CD は採用しておりません。
コマンド一発で deploy できるようにはなっていますが、開発環境・検証環境へのデプロイのタイミングはエンジニアに任されています。
本番環境へのデプロイは週に一回実施します。
onCall はどの程度発生している?
週に数件程度です。
サービスの性質上、予約が不成立の場合も onCall にするように設定していますが、不成立の理由が 500 系のエラーでなければ、追加対応は不要です。それを除けば、週に数件あるかどうかです。
自動リカバリーがあるので、onCall が発生した場合でも、業務時間に原因を調査する事がほとんどです。
Nutmegに参加して 3 年たちますが、夜中に起きて対応したことはまだありません。
Andrew がハワイで開発を行っているので、時差を利用してお互いフォローしています。
SLA はどの程度?
99.99 % 以上です。安定してサービスを提供できている自信があります。
いかがでしたでしょうか?
エンジニアにとってはなかなか興味をそそられるのでは無いかと思っています。
というわけで、我々はフルタイムで取り組んでくれるエンジニアを熱望しています!
面接ではなくカジュアルに話して応募の判断をしたいという方も歓迎していますので、気軽にご連絡ください