感想: Unleash Mercari Tech! vol.4 〜メルペイ立ち上げ当時に戻ったら?〜

llll
·

技術書典16の「Unleash Mercari Tech! vol.4 〜メルペイ立ち上げ当時に戻ったら?〜」を読んだ。とても面白い本だったので、自分も「当時に戻ったらやり直したいこと」を書き残す。会社を辞めてから4-5年が経っているので、既に実現されていたり必要なくなったものがあるかもしれない。

私は元々メルカリ社に経理として雇われ数年働いていたが、メルペイ立ち上げ当時は内製の会計データ基盤を開発・運用するチームのプロダクトマネージャーに転職していた。社内では「会計システム」と呼ばれていて、メルペイを含むメルカリグループが運営するサービス内で生じた債権や債務、収益や費用を集計し財務会計用のレポートを生成するためのシステムだった。一般的にはこの「会計システム」という単語からは別のものが想起されるだろうから、もっと良い名前をつけておけばよかった。

メルカリがリリースされてから数年は、本番データベースのレプリカから必要なデータのみをエクスポートし集計用のデータベースや DWH にインポートして複雑な SQL を実行するような ETL 処理でレポートを出力していた。SQL が複雑になっていた主な理由としては「会計で必要なデータ」と「サービスで使われるデータ」との間に構造的なミスマッチが生じがちという背景があった。会計で利用する全てのデータがイミュータブルかつデータベースに保存されていればさほど大変ではないのだが、現実的にはそうなっていない場合が多い。

上場前後の財務諸表監査や IT 内部統制監査では特に問題はなかった。なお、ここで「なかった」とは問題が全く存在しなかったわけではなく、財務諸表がすべての重要な点において適正に表示されているかに関する監査人の意見表明に重大な影響を与える程の問題がなかったということを意味する。つまり問題はあった。例えば以下のような...

  • 集計ロジックに使用しているカラムが集計後に更新され、翌月に再集計した時の結果が変わっている

  • あるカラムに入っている JSON を解析して中間テーブルを生成し別のテーブルと JOIN して...という非常に複雑な処理で集計している数値がある

  • 障害やイレギュラーな処理、いつの間にかリリースされている新機能や新サービス等の影響によって、集計結果と取引先等への債権債務が不整合となる

私は問題が大きくならないように、月次決算の度にレポートの数字と債権債務のあるべき残高を比較し、差異があれば SQL を書いて調査し、チームのエンジニアの方にレポートの集計クエリやプログラムを修正していただき修正結果を財務諸表に反映して...必要に応じて監査人と対話して...という仕事をしていた。これにより自分自身がメルカリのデータ構造、事業で生じる債権債務や収益費用の構造や資金の流れ、SQL の文法やデータベースの仕組みに詳しくなるというメリットはあったものの、持続可能な仕組みではないと感じていた。

メルペイの立ち上げは最初からマイクロサービスで始めるという意思決定がされていた。それに際して、会計システム側もマイクロサービス環境に対応する新しいアーキテクチャに移行することが決まった。この話は会社のテックブログにも書いたが、要するに会計処理が必要なイベントを事前に定義しておき、そのイベントが発生した時に予め定義された形式のデータを各サービスから送信してもらい、それを検証するためのインターフェイスのようなものを用意してデータを検証・保存、集計することになった。

私の中では、メルペイの開発やメルカリ全体のマイクロサービス化を機に会計の問題を全て解決して綺麗にしたいという意識があった。結果的には同じチームのエンジニアの皆さんやメルペイの優秀な方々のおかげで主要な目標は達成できたものの、自分自身の働きを自己採点すると60~70点といったところだ。大きな方針としては誤ってないと思うが、振り返るとたくさん改善できたことがあった。

まずはドキュメント化について。仕様に限らずシステムを支える思想や過去の背景、前提とする状況や発展の方向性などアーキテクチャや思想に関する整理されたドキュメントを残しておけばよかった。リリース当初はこれらを議論し理解し実装した人々でチームが構成されているが、チームや会社のメンバーが徐々に入れ替わる中で周囲の環境に応じてシステムが進化していくために、その役割や責任を明確にしたり他のチームとコミュニケーションを取っていく必要がある。その上で、開発時に議論したことや決めたことを残しておく価値は大きい。自分が退職時に引き継いだ PdM の方はすぐ辞めたし、後になってチームの皆さんもさまざまな理由で入れ替わったと聞いた。

自分は過去の負債を返済したつもりになっていたのだが、負債は瞬間的な意思決定だけでなく周囲の環境に応じて徐々に生まれるものなので、持続的に環境に適応するための体制づくりまで含めて仕事をすべきだったと思っている。それをやらずに退職した人間が後から言うことではないのだが...

次に、データ構造について。財務会計のための報告をするシステムなので、その目的に必要なデータ(各サービスで起きるイベントと会計処理の関係と、それに付随する税区分や取引先等の情報)を含むようなスキーマを定義していた。一方で、メルペイ開発の過程で経理やクライアントとなるマイクロサービス側で分析等に使うためのデータを合わせて保存する需要があり、それを格納するための汎用的なカラムを用意することにした。どのサービスがどのカラムにどのようなデータを送ってくるかは当初スプレッドシートで管理していた。つまり、同じカラムでもイベントによって格納されるデータが異なるいわゆる EAV(Entity Attribute Value) と呼ばれる状態になっていた。この構造自体は要求を満たすために程度仕方ない部分もあったが、メタデータの管理には大いに工夫の余地があった。少なくともスプレッドシートは運用の負担が大きいので優先的に解消すべきだった。

また、各サービスで起きる一つのイベントにつき会計処理のイベントが複数発生するような関係になっていたので、イベント同士の関係性(例えばこのイベントの後にはこのイベントが来る...といったような意味的な順序性)を定義して事後的にデータの完全性を検証するような仕組みを用意してもよかったかもしれない。

次に、引当金の取り扱いについて。引当金って何?と思った方はポイント引当金について以前ブログに書いたので読んでほしい。メルペイのような事業ではポイントとあと払い債権が引当金の要件を満たし、財務会計で引当金を計上しなければならない。ここで問題になるのが、引当の処理が純粋に会計の都合で必要であり、決済やメルカリ上の取引といった各マイクロサービス上のイベントと会計処理の 1:1 の関係ではないということにある。つまり既存のイベントにフックするのではなく会計のためだけに集計してイベントを送ってもらうか集計に必要なイベントを全て送ってもらい会計側で計算するかになるのだが、当時は余裕がなかったので経理の方と話して「とりあえず」システムの外で別に集計するようにした。しかし、この「とりあえず」で始めたものが新しいシステムに組み込まれることはなかった。少なくとも自分が働いていた間は...

振り返ると、前述のデータ構造の話とも共通しているのだが複式簿記という根源的なデータモデルの範疇でシステムの振る舞いを表現するのが良かったと考えている。最近 Stripe が "Ledger" と呼ぶ社内帳簿システムに関する技術ブログを読んだのだが、ここでは Stripe プラットフォーム内の論理的な資金フローを抽象化したセマンティックなデータストアとしての「帳簿」内での項目間の残高移動によって状態遷移を表現している。

複式簿記は本質的に、財政状態(これは「報告主体が過去の事象の結果として支配している経済的資源及びそれを引き渡す義務」とみなすことができる)を細分化し、その項目間の移動または on/off balance として状態遷移を表現するデータモデルである。Stripe の Ledger は物理的な資金フローだけでなくシステム内の状態遷移を複式簿記の形式で表現し簿記の概念を用いてシステムが正しい挙動をしているか検証するという点が自分にとっては目新しかった。今から作り直すとしたらこの Stripe の技術ブログを大いに参考にすると思う。

次に運用と管理画面について。メルカリがリリースされて数年間は会計システムを動かす環境の運用を SRE のような専門のチームに依存していたが、メルペイの立ち上げ当時はマイクロサービス化に伴い各チームで本番/Dev/QA環境を運用することになった。その中で、会計のチームでも本番環境へのマスターデータ登録やインフラのメトリクス監視、障害対応など運用関連のタスクが増加した。運用業務を楽にするような管理画面やツールの開発、 SLI/SLO の明確化などをもっと早く着手すれば良かった。

次に、データのバックアップと FinOps について。運用開始当時は計算資源を贅沢に(?)使っていたが、毎月費用がかかること、そしてイミュータブルなイベントログで線形増加し続けるというデータの特性を考えると早くからデータの特性を活かした費用面での最適化に取り組めばよかった。例えば、データベースの日次バックアップを長期間にわたって保存する必要はない。IT内部統制の観点からは財務諸表に使われているレポートに再現性があれば基本的に十分で、レポートの生成は月次で行われているので生成時点間の日次バックアップは廃棄することができる。実際には他のチーム向けに出力するユースケースが他にもあったのだが、出力時点のバックアップがあれば出力と出力の間のバックアップは必要なくなることが多い。さらに、会計というドメインの特性からすると古いデータは利用頻度が著しく低いと考えられるのでアーカイブ用のストレージクラスに入れることもできる。

次に、実装コストについて。新しい会計システムでは会計処理データの送付や突合用の API 呼び出しを各マイクロサービスに依存しているので、各チームにデータ送付や突合のための開発をしてもらわなければ責任を果たすために必要なデータを入手できない。しかし、会計関連の開発の優先度は後回しにされがちでスケジュール的に皺寄せが来ることもあった。この点については、参照できる実装や SDK のようなツールを早めに用意できればよかった。

最後に、各サービスのオーナーシップについて。新しい会計システムではデータの送付や突合を各マイクロサービスに依存していたので、会社単位で正確かつ適時な会計報告を行うには、各関係者がそれぞれの責任を果たす必要があった。それに伴いプロジェクトの背景やそれぞれの関係者に対応してもらう内容をスライドやドキュメントにまとめ説明して回ったが、合意形成することが難しいチームもあった。そのチームのために別の作業が発生することもあり...(省略)。要するに「マイクロサービス化」という目的に従うあまり自由に放任しすぎた。「最低限ここは守ってほしい」というようなガイドラインを用意すべきだったかもしれない。


振り返ると他にも「これもやっておけばよかった」という仕事がたくさんある(書けない or 書きたくない話もある)。

しかし、現実世界では自身の能力、与えられた時間、周囲の環境...など様々な制約の中で最善の仕事をするしかない。そういった中で生まれる苦難の先にこそ更に面白い苦難があるので、自分もそれを得る機会を作り出していきたい。そう思える本だった。

@llll
経理 → プログラマー