フルスタックDartからRustバックエンドへ

この記事は10X 新春ブログリレー 2026の1月5日分の記事です。


弊社が提供するネットスーパーのサービスは、モバイルアプリとWebはFlutterアプリ、バックエンドはDartのgRPCサーバーで実装されています。isomorphicではないですが、言語統一がされたフルスタック的な状態と言えると思います。

バックエンドでのDartはマイナーであり、それに伴って様々なデメリットもありました。それらを乗り越えたり飲み込んだりしながら、5年ほどサービスを運用してきましたが、これから先は方針を転換することに決めました。

この記事では、我々が何故フルスタックDartから方針転換することにしたのかと、今後のバックエンドの言語としてRustが有力になっている背景を説明します。

方針転換のきっかけは採用

バックエンドのDartでは様々な問題にぶつかってきましたが、どれも方針転換に踏み切るほどにはならず、なんとか対処してきたのがこれまでです。そんな中、方針転換のきっかけとなったのが採用です。

事業の初期フェーズではマルチスキルのソフトウェアエンジニアで開発チームを構成し、技術領域で役割を分けないやり方をしてきました。事業のフェーズが進むにしたがって、バックエンドの開発ニーズが高まりましたが、世間のバックエンドエンジニアからすればDartは積極的に選びたい言語ではありません。マネジメントの立場としてはバックエンドを強化したいが、技術スタックがマッチしていないという状況になっていました。

技術的な課題であればなんとかできる可能性もありますが、採用と技術スタックのアンマッチは変えない限りはどうにもなりません。バックエンドにおけるDartの立ち位置が変わるのを待つか、自分たちがバックエンドで使う言語を変更するかを考えた時、会社としては後者を選ぶことに決めました。

バックエンドのDartのふりかえり

次の言語を選ぶ前に、バックエンドにおけるDartのメリットとデメリットを整理しました。

メリットとしては以下のものがありました。

  • 静的型付き言語として程々に機能が揃っている。nullabilityやmutabilityの制御ができる、網羅性検証つきのパターンマッチがある、といったラインは抑えられており、ロジックの記述における不便は少ない。
  • 学習コストが高くない。言語仕様はJavaとKotlinの間くらいという感じで、際立った特徴は少ないのでキャッチアップしやすい。複雑な型制約などが書けないこともあり、言語の理解度の差による実装方法に差が大きくなり過ぎない。
  • シングルバイナリで動かせる。

デメリットとしては以下のものがありました。

  • バックエンドのエコシステムが未成熟。ミドルウェアのドライバはあったりなかったりで、あっても不安なものもある。外部サービスのSDKはまずない。モニタリングや分散トレーシングの実装も少ない。
  • 基本的にはシングルスレッドであり、CPUバウンドな処理はつまりやすい。Isolateで逃すことはできるが、Isolateの立ち上げが重い、メモリ共有ができない、スタックトレースが分断される、といったハードルがあり、広くは使いづらい。

キープできるメリットはキープしつつ、解消すべきデメリットは解消することにしました。

運営自律性という事業上の特性

言語の候補を選ぶ上では、我々の事業に合っているかどうかも考慮しました。

10Xの社内には運営自律性と呼ばれる特性があります。システムの利用者が失敗をタイムリーに認識し、自力で訂正できる状態になっているかどうかを指すものです。プロダクトが扱う業務フローが複雑で、多様なシステムとも連携する必要があるため、運営自律性の有無は運用コストに大きく影響します。

運営自律性はタダではなく、それなりのコストを払う必要があります。開発者がエラーをトレースできるだけでは不十分で、エラーを業務上の意味のあるアプリケーションの仕様として扱うため、その分の実装コストが乗るためです。このコストを払うべきかはプロダクトによって異なると思いますが、我々のプロダクトでは必要だと判断しています。

運営自律性の得やすさは、言語がエラーをどう扱うかに左右されます。最下層のレイヤーのエラーから利用者に見せる最上位のエラーまで漏れなく仕様を定義して変換することを前提とすると、一般的な例外や、型なしのエラーでは、コンパイラによる網羅性検証に頼れなくなるため、その分不利になります。そのため、一貫して型付きでエラーで扱える言語が、事業に適していると判断しました。

現在はRustを検証中

これまでに説明した論点を踏まえて色々と検討した結果、現在はRustで一部のシステムを置き換えの検証を進めています。実装面ではかなり良い手応えを得られていて、幅広いエラーを漏れなく仕様に反映する営みが自然に回せています。一方で、人材の多さやエコシステムの充実度という意味では少し不安もあります(それでもDartよりは遥かに良いですが)。

現状不安を感じている点も踏まえて飲めるものか判断し、最終的な決定に進む予定です。

また、今回決めようとしているのはあくまで汎用的にバックエンドで使う言語であり、特定の言語を使った方が良い場面では引き続きその言語を使うことになると思います。Go、Python、TypeScriptに関しては明確にそういう箇所があり、併用していく予定です。

おわりに

以下のインタビューに、Dartで統一した時の状況がよくまとまってました。 https://type.jp/et/feature/15075/

Dartで統一するまでの壁や、統一したことによるメリットなどを話しているのですが、最後は以下の言葉で締めくくられていました。

――中には、あえて言語を統一せず、そのときどきの現場判断で10以上の言語を使っている開発組織もあると聞きます。石川さんは、エンジニアリング組織はどうやって言語選択していくべきだと思いますか?

大切なのはその言語を使う目的と「どんな問題を解決したいのか」を考えることだと思います。10言語を扱っている組織にしても、きっと事業フェーズやプロダクトの状態など、その時抱える課題や目的に応じて最適な方法を選んでそうなっていると思うんですよね。

うちの会社もプロダクトが増えたりして、Dartだけでは困るような状況になれば、また言語を増やすことだってあるかもしれません。流行っているからといって組織やプロダクトが抱えている問題を解決できないなら、その言語を採用すべきではないですし、新しい言語で自分たちが解決したい問題を解決できるなら、そのためのハードルはフットワーク軽く乗り換えるべき。

組織のフェーズや目的によって正解が違うので、ただ「新しいから」「人気だから」ではなく、その時に抱えている課題を解決するために、言語を選び取っていくスタンスが大切なのだと思います。

上記で触れている"その時に抱えている課題を解決するため"に大きな変化を起こす時が来た、というのが今なのでしょう。

サービスは5年続けることができましたし、今の調子を考えると10年以上は続きそうです。プロダクトの中には、このままで10年目を迎えられる箇所もあれば、このままでは事業成長のボトルネックとなる箇所もあります。何をどう変えるかによって10年目の状態が変わるので、技術的な変化の価値が高いフェーズでもあると思います。

難しいですが、上手くやって良い業績を出せるソフトウェア開発に挑戦していきます。

仲間募集

10Xはそんな感じでエンジニアリングしていきたい仲間を募集しています。ピンと来た方は是非1度話しましょう。

10x.co.jp