プロダクトのアーキテクチャ見直しでRustを採用することに
──まずは自己紹介をお願いします。
フルカイテン株式会社でプロダクト開発部 部長を務めています、横田敦志です。2020年10月にバックエンドエンジニアとしてフルカイテンに入社しました。その後、RustによるGraphQLサーバー構築、データ基盤のアーキテクチャ構築に携わってきました。現在はマネジメント業務、採用、開発生産性、アーキテクチャなどの領域を担当しています。

──現在のエンジニアチームや開発体制の規模・特徴を教えてください。
プロダクト開発部は社員と業務委託をあわせて、約30名のチーム構成になっています。そのうち、Rustを書いているエンジニアは5名です。
またフルカイテンでは、仕様策定の段階からPMやエンジニアだけでなく、顧客と直接接しているカスタマーサクセスもドメインエキスパートとして参加します。現場の知見を取り入れることで仕様の解像度が高まり、プロダクト全体に「手触り感」が生まれ、自分の意見も反映しやすい環境になっているところがいいと感じています。
──ちなみに、現在の働き方はリモートですか?
エンジニアは全国に散らばっているため、基本的に全員フルリモートです。フルカイテンではマルチプロダクト戦略を採用し、まずPoCで実証実験を行いながらコンセプトを磨き、最終的にプロダクトへと発展させていく流れで開発を進めています。専門性が高い職種で分かれつつも、プロジェクトチームを横断的につなげています。プロジェクトの立ち上げごとの組成やまとめていく部分は難しさもありますね。
──貴社では「Rust」を採用しているそうですが、どのような経緯で取り入れたのでしょうか?
私が入社した時点では「FULL KAITEN」は旧バージョンで、顧客データの急激な増加により、当初想定していたシステムの処理性能の限界を超えている状態でした。「画面表示に時間がかかる」、「日次バッチがなかなか終わらない」といった課題が顕在化し、部分的な対応では追いつかず、アーキテクチャを根本から作り直すしかない、という判断になりました。
旧バージョンはPythonで書かれていたのですが、集まったメンバーの技術スタックは、私がPHPやTypeScript、Kotlin、他のメンバーはRubyやPython、Javaという具合にバラバラで、特定の言語に固執する必要がなく、どの技術を選ぶかをフラットに議論できる状況でした。
選定の際に最も重視したのは「静的型付け言語」であることです。型を厳密にすることで、長期的に生産性や保守性を高められると考えたからです。Webアプリケーションとして動作できることは大前提でしたが、フルカイテンでは大量のデータを扱う場面が多いため、パフォーマンス面も重要な要件でした。また、エンジニアの人数が限られていたことから、サーバー保守などのためのCLIツールも同じ言語で開発できるものが効率的だと考えていました。
他の静的型付け言語では、TypeScriptは型がやや緩いと感じていたので、クロスプラットフォームで使えて、かつ高速となると、最終的にはGoとRustに絞られました。
──では、GoとRustの二択でどうしてRustを選ばれたのでしょうか?
チームメンバーの一人が趣味でRustを書いていて「Webアプリケーションでも問題なく使える」と話してくれたことが大きな後押しになりました。
正直、GoとRustのどちらでも良かったのですが、せっかくサービスをゼロから構築できるチャンスが目の前にあるのなら“わくわくする”ほうでチャレンジしてみたいと思ったんです。
──“わくわくする”ほうを選ばれたのですね。
そうですね。加えて、当時は国内でRustの導入実績がまだほとんどなかったので、それ自体がエンジニアに向けたフルカイテンの差別化要因になるのではないかと考えていました。他社の採用記事で、「Scalaのような当時まだ採用実績が少ないモダンな言語を選んだことで、優秀なエンジニアの目にとまり、逆に応募者が多くなった」という話を読んだことがあります。Rust導入でも同じような効果が得られるのではと期待していました。
──導入に際し、社内で調整や説得は必要でしたか?
現場のメンバーが「これでいこう」と合意すれば進められる環境だったため、そういった調整は特にありませんでした。私自身、過去に保守的な選択をして後悔した経験があったこともあり、新しい言語に挑戦するのはとても良い成長のチャンスだと考えていました。それを逃してしまうのはもったいないという思いもありました。
導入が早くて苦労もあったが、静的型付け言語で堅牢に書けてコストメリットも
──現在、Rustはどのように使っていますか? また、苦労した点も教えてください。
RustはWebアプリケーションの開発に加えて、CSV作成や集計処理などのバッチ処理をLambda上で実行する形でも使っています。
苦労した点としては、導入当初は非同期ライブラリのエコシステムが十分に整っておらず、WebアプリケーションとLambdaのランタイムやバージョンを統一させる工夫が必要だったことです。具体的には、WebアプリケーションのフレームワークであるActix Webのバージョンが3だった頃、Lambda側が求める非同期ランタイムのバージョンと合わず、ランタイムを指定して調整する必要がありました。なお、これは導入が早すぎたために発生した問題で、現在は解消されています。
関連してActix Webのバージョン3から4にアップデートする際も、ライブラリの依存関係が複雑で、想像以上に大変でした。こうした細かい問題はいくつかありましたが、チームで検証を重ねながら、段階的に解決していきました。
──利用しているツールで特徴的なものはありますか?
Rustで書かれたタスクランナーのcargo-makeがあります。サーバー関連のメンテナンスなどちょっとした作業でも、複数の処理フローを一つのコマンドにまとめられるため、作業手順をコードとして管理しやすく、チーム全体で操作を統一できます。そのため、Rustを使っているチームだけではなく、データ基盤チームでも活用しています。タスク定義はRustと同じTOML形式で記述できるので、読みやすくメンテナンスしやすい点がいいですね。
──Rust導入後に改善した業務プロセスや技術的な成果などはありますか?
まず、一番大きいのは、コードの品質を高めやすく、安定性がある点です。コンパイラによる強力な静的チェックがあるため、リファクタリングを安心して行えますし、バージョンアップもスムーズに進められるようになりました。ビルドが通ればほぼ期待通りに動作するため、常に最新バージョンを保ちながら小さな差分で開発を進められるのは大きなメリットです。
また、性能面でも恩恵があります。例えば、AWS Lambda上で数百万件規模のCSVを生成する処理があるのですが、メモリ効率が良いため大規模データでも安定して処理できています。