♻️

技術的負債を解消し、事業成長に繋げるためのリアーキテクト

に公開

はじめに

ChillStack では、経理部向けに経費申請から不正・不備を自動で検知する「Stena Expense」というサービスを提供しています。
数年サービス運用を続ける中で、プロダクトの成長や計画のアップデートに伴い、技術的負債が発生していました。

この記事では、技術的負債を解消するために行ったリアーキテクトの背景と取り組みを紹介し、
プロダクトの成長を阻む技術的負債に対して、どのように取り組むべきかの参考になれば幸いです。

技術的負債への取り組み

多くのプロダクトでは、開発・運用を続ける中で技術的負債が発生します。発生した技術的負債の解消には一定のコストが必要になるため、どのタイミングで取り組むべきか悩まれている方も多いと思います。
さらには、開発の内側から見えてくる課題であるため、ビジネスサイドと問題意識を共有しにくく、小さな負債だと解消の意思決定が進まず、後回しにされてしまうこともあります。後回しにすることで、負債に依存する箇所が増え、負債を認知したときよりも解消にかかるコストが増大していきます。
その結果、プロダクトの成長を阻む要因となり、最悪の場合、開発チームの生産性やユーザー体験に悪影響を及ぼすこともあります。

Stena Expense開発チームでは 技術的負債を「プロダクトの成長を阻む事業的リスクや課題」 として捉え、解消に向けた取り組みを積極的に行っています。
このような取り組みが行えるのは、中長期的な視点でプロダクトが目指す姿を開発・ビジネスチーム双方で共有しており、その姿に向かうために解決すべき課題やリスクをチームが裁量を持って進められるからです。

リアーキテクトを始めたきっかけ

Stena Expenseチームでは、数年スパンの製品ロードマップを策定し、長期的なプロダクトの成長を見据えた開発計画を立てています。
また、ロードマップの見直しを定期的に行っており、事業が成長していく過程で学習したことをロードマップに反映しています。
その中で、より深いお客様の課題を解決する「分析機能」を製品ロードマップに組み込み、本格的に分析機能の開発に着手しました。

一方で、分析機能の開発が決定し、プロダクトの方向性がアップデートされたことで新たな問題が浮かび上がってきました。
例えば、Stena Expenseではお客様の立替経費のデータに対し、それ以外のさまざまなデータ(ETC利用履歴やタクシー配車履歴、コーポレートカードのトランザクションデータなど)を掛け合わせて、総合的に不正・不備の検知を行います。
このような機能をプロダクトで実現する上で、立替経費のみが厳密に管理されており、それ以外のデータはあくまでも付属データとして扱われていました。
しかし、分析機能では、付属データとして扱っていたETC利用履歴やタクシー配車履歴などの支払データも、立替経費と同様に厳密に扱う必要が出てきました。
さらには、長年にわたる運用でスケーラビリティの問題や不正検知モデル開発の複雑さといった技術的負債も積み上がっていました。

そこで、プロダクトの基盤となっているアーキテクチャを見直すという非常に大規模な「リアーキテクト」作業を製品ロードマップに組み込み、チーム全体で取り組むことにしました。

解決すべき負債

[負債1] データ構造の非統一

ETC利用履歴やタクシー配車履歴など、立替経費以外の支払データは、不正検知に必要なデータのみが管理されていました。
そのため、必要最低限の形でのみデータを保持しており、構造が統一されておらず、様々な観点でデータを取り回すことが難しい状況でした。

[負債2] インフラ構成の制約によるスケーラビリティの限界

検知処理の中核を担うサーバーが単一構造となっており、並列処理ができず、1件ずつ順番に処理する設計になっていました。
この構成は、導入企業数の増加に伴い深刻なボトルネックとなり、処理待ち時間の増加やユーザー体験の劣化を招いていました。加えて、オートスケーリング機能にも未対応で、柔軟な拡張性に欠けていた点も負債となっていました。

[負債3] 属人性の高いモデル運用

Stena Expenseでは、エンタープライズのお客様ごとの細かなニーズに答えるため、データ形式や検知モデルを個社ごとにカスタマイズしています。
その際、検知モデルに必要な特徴量の生成やデータ統合処理が、一部のエンジニアしか理解していない巨大なモノリススクリプトとして実装されていました。
このスクリプトは、処理の流れが不明瞭で、どこで何が行われているのかを把握することがきわめて困難でした。その結果、再現性やメンテナンス性が著しく低下し、属人化による開発リスクが高まっていました。

負債への解決方法

[解決1] データ構造の統一と柔軟化

[負債1] に対する解決として、支払データごとの構造を抽象化・モデリングを行うことで、プロダクトへ取り込みを行うための柔軟な設定やフォーマットを合わせるための処理機能を追加しました。

この結果、あらゆる種類のデータに応じて適切に取り込めるようになり、分析機能の開発に繋がりました。

[解決2] スケーラブルな検知基盤への刷新

[負債2] に対する解決として、検知処理のフローを複数のステップに分割し、スケーラブルな検知ワークフローとして再設計しました。下記に具体的に再設計した内容を例示します。

  • アップロードから検知完了の通知までの一連の処理を細かくステップに分割
    → データの取り込みや検知、完了通知などの工程に分離することで、処理内容の見通しが良くなり、柔軟な制御が可能になりました。
  • ステップ全体を一つの検知ワークフローとして定義
    → 処理単位ごとではなく、アップロードから集計までの一連の流れを一つの検知ワークフローとして設計し、それを複数並列に実行可能な構成とすることで、スループットと可用性を大幅に向上しました。
  • 各ステップの実行ステータスを一元管理
    → 各処理の進行状況を把握しやすくなり、障害発生時の切り分けやリトライ処理も容易になりました。

この再設計により、処理のスケーラビリティが大幅に向上し、大量データの高速処理と安定した運用を実現しました。

Stena Expense は Google Cloud Platform (GCP) 上で稼働しているため、GCP の Workflows を利用し、検知ワークフローを定義しました。各ステップでは、 Cloud Run 上で処理を実行する形にすることで、処理の並列実行が可能になり、スケーラビリティと可用性を大幅に向上させました。

検知ワークフローのアーキテクチャ図
検知ワークフローのアーキテクチャ図

[解決3] 属人性を排除したモデル運用

[負債3] に対する解決として、今まで1つのスクリプトで行っていた処理を1つずつ紐解き、データの生成・選択・削除およびデータ型や形式の統一といった前処理を独立した機能として追加しました。
前処理を独立させ、検知ロジックを副作用のない純粋な処理として切り出したことにより、開発効率が大幅に向上しました。新しい検知ロジックの追加にかかる時間は短縮され、データのパース、前処理、ロジックを独立してテストできるようになったことで、全体的な品質向上も実現できました。

運用面では、巨大なモノリススクリプトの解体により、メンテナンス工数を大幅に削減することができました。これまで特定のエンジニアに依存していた状況から脱却し、複数のエンジニアが並行して検知ロジックの改善に取り組める体制を構築できました。
今後は、エンジニア以外のメンバーも検知ロジックの改善に参加できるよう、さらなる機能改善を進めていく予定です。

新アーキテクチャへの移行

Stena Expenseは、すでに多くのお客様にご利用いただいています。そのため、この新しいアーキテクチャへの移行に際し、お客様への影響を可能な限り減らし、安全に移行を進める必要がありました。

[ステップ1] 移行対象の洗い出し

まず、検知モデルやAPI、バッチ処理など、各コンポーネント間の依存関係を明確にし、影響範囲を網羅的にリストアップすることで、全体像を可視化しました。

次に、システムが実際に利用されるユースケースを列挙し、それに基づいて移行に必要なデータおよび機能要件を整理しました。

さらに、整理したユースケースをもとに、支払データごとに異なっていたデータ構造や制御フローを洗い出し、共通インターフェースへと統一しました。これにより、設計の簡素化と保守性の向上を図りました。

[ステップ2] 移行手順の整備

ステップ1で移行対象を洗い出した後、すべてを一度に移行するのではなく、お客様ごとに段階的に移行できるよう、検証環境にて数回試したのち、移行手順を整備しました。
これにより、開発チームの移行時の混乱を最小限に抑えることができました。

さらに、移行期間中の旧構成と新構成の共存に備え、「フィーチャーフラグ」としてお客様ごとに構成を切り替えられる仕組みを導入することで、お客様への影響を最小限に留め、安全かつ段階的な移行を実現しました。

[ステップ3] 工数の見積もりと優先順位付け

ステップ1で整理した影響範囲の大きさや既存コードの複雑さをもとに、ステップ2の各作業の工数を見積もり、合わせてQAや検証に必要な工数も積算しました。

さらに、大規模なリプレイスによるリスクを避けるため、段階的な機能移行と新旧構成の並行稼働を採用し、サービス提供への影響を最小限に抑えつつ、安定した開発スピードを維持しました。

リアーキテクトで得られた結果

あらゆるコストデータが一元管理可能に

  • 個人経費に加えて、ETC利用履歴・タクシー配車履歴など、これまで厳密に管理されていなかった支払データを共通フォーマットに統一
  • 全データが一貫した構造で集約されることで、横断的な分析が可能に

スケーラブルな検知インフラへ移行

  • 処理負荷に応じたオートスケーリングが可能なアーキテクチャへと刷新
  • 企業数や従業員数の増加、突発的な利用集中といったスケール変化にも柔軟に対応でき、安定したサービス提供を実現

検知ロジックの分離・再構築

  • 特徴量生成や検知ロジックを独立したコンポーネントとして再設計
  • 新しい検知モデルの導入や特徴量の追加が容易になり、プロトタイプの検証から本番反映までのサイクルが大幅に短縮
  • 結果として、現場からのフィードバックを素早くプロダクト改善に反映できる体制を整備

新しいアーキテクチャでの運用は始まったばかりですが、これらの取り組みによって、プロダクトの成長を支える基盤が整い、今後の機能追加や拡張に対する柔軟性が大幅に向上しました。

最後に

開発チームでは、技術的負債を解消することは単なるメンテナンスではなく、事業成長のための戦略アクションと捉えています。
技術的負債の解消は、ソースコード上の問題だけではなく、プロダクトを持続的に進化させ、ユーザーに価値を届け続けるために欠かせない投資です。
だからこそ、ビジネスサイドの理解も得ながら、適切なタイミングを見極めて、定期的に工数を一定かけて行うことが、長期的にプロダクトを運用する上では非常に大切だと考えています。

今後も、プロダクトのあるべき姿を目指しながら、開発体験の向上と技術的チャレンジを両立させ、組織全体の技術力を高めていきます。


ChillStack ではプロダクトを一緒に育ててくれる仲間を募集しています。
「今は転職する気はないけど、ちょっと興味を持ったので話を聞いてみたい」という方も大歓迎ですので、ご興味ある方お待ちしてます。

会社概要
https://chillstack.com

採用ページ
https://chillstack.com/career

公式 Note
https://note.com/chillstack

株式会社ChillStack Tech Blog

Discussion