もし過去に帰れるならもっと早く導入したかった開発の取り組み

この記事は🎄10X プロダクトアドベントカレンダー2023の22日目の記事です。

21日目の昨日はaineさんによる「プロダクトマネージャーになった自分が大事にしていること」でした。


こんにちは。エンジニアリングマネージャーの坂本(kazu0620)です。

この記事では10XがStailerの開発に取り入れて来た仕組みやルールの中で、「もしも過去に帰れるならこれは早い段階で取り入れたい」と私個人が特に思ったものたちを紹介したいと思います。

過去に帰ることはできませんが、我々と同じようにプロダクト開発を行っている組織の方の参考になれば幸いです。

Stailer最初期の開発と現在

Stailerの開発が始まったは2019年末のことです。私が10Xに入社しStailerの開発に関わり始めた2020年3月の時点では、ソフトウェアエンジニアの数は6名でした。当時はプロダクトマネジメントはCTOであるishkawaが担当し、まだデザイナーや品質管理に携わるメンバーはいない、という状況でした。

ここから3年半で、開発組織は成長し、今ではプロダクト開発に携わるメンバーの数は50名を超えています。これまでの過程で10Xの開発組織は、Stailerのエンドユーザーやパートナーに早く安全に価値を届けるための制約やプロセスを、数多く加えて来ました。下記は特に印象に残っているものを記載してますが、他にも多くの取り組みや試行錯誤があります。

時期 導入したもの
2021年4月 コードレビューの必須化
2021年11月 Desing Docの運用開始
2021年12月 開発チームの組成
2022年 7月 シフトレフト化によるQAプロセスの改善
2022年8月 Stailer開発ライフサイクルの策定
2022年10月 アプリケーション仕様書の確立
2023年1月 ADRの運用開始
2023年4月 ドメインベースの開発体制への移行
2023年5月 技術的意思決定会の開始
2023年7月 SLOの運用開始

ちなみに、開発初期からこれら全てを揃えて開発を進めるべきか、というと私はNoだと考えています。事業もプロダクトも不確かな状態で、初期から制約やプロセスを増やしすぎると結局事業自体が立ち上がらない、というリスクのほうが大きいと考えているからです。特にプロダクト開発の最初期はスクラップアンドビルドを繰り返す必要があり、あまりに早い段階で制約を設けすぎると、事業やプロダクトの生存可能性をかえって下げてしまうというケースもあるのではないかと思います。

プロダクトの複雑さや守るべきものを守れなかったときのリスク度合いなど、さまざまな要素に応じて徐々にプロセスや制約を追加していくべきだと思います。

ただ、それにしてもこれは早く取り入れておけばよかった、もう一度過去に戻れるなら早い段階から導入してみたい、というものもいくつか存在しています。本日はそうしたものを3つ、紹介したいと思います。

Design Docの導入

Design Docは、システム設計のデザインを記述するものです。永続的にメンテナンスするもの、というよりは、実装に入る前に設計を議論しレビューするためのツールとして10Xでは利用しています。フォーマットはデザインごとに任意ではありますが、以下のような項目を記載することが多いです。

  • 目的
  • Goals
  • Non Goals
  • 選択肢とPros / Cons
  • アーキテクチャ
  • テストやモニタリング、リリースのプラン

Design Docは2021年11月に導入したのでStailerの開発が始まってから2年を経て導入した、ということになります。その2年間の間にも、10Xでは重要なシステムの意思決定を数多く行なって来ました。

Design Doc導入前も設計上気にかかる部分があれば他のメンバーと相談したり、レビューを依頼したり、といったことはしていました。

しかし、やはりフローやフォーマットが正式に存在していることによる敷居の低さ、「これくらい複雑な設計ならDesign Doc書いた方が良いな」という心理が働くことから、Design Doc導入前に比べると設計に関する議論やレビューは盛んになっています。

また、設計に関する議論が実装前・リリース前に行われることにより、コードレビューで大きな手直しが入ることや、ベストではない設計でリリースしてしまったがゆえに負債となってしまう、といったようなことを防ぐことができていると感じます。

こうした恩恵を考えるとDesign Docは、任意かつフォーマットが軽量なものでもよいので、開発初期から取り入れていてもよかったな、と今振り返れば思えます。

ADRの導入

ADR(Architecture Decision Records)は、アーキテクチャや開発プラクティスに関する意思決定の内容や背景を記録し共有するためのドキュメントです。Design Docは設計を考える上での議論に使うフロー型のドキュメントであるのに対し、ADRは決定事項をメンテナンスし続けるストック型のドキュメントになります。

ADRは、以下のようなフォーマットに沿って記載します。

  • 意思決定のコンテキスト
  • 決定内容
  • 影響
  • コンプライアンス(決定をどう遵守するかの方針)

ADRの効用として、チームにとって何が標準であるのか・なぜその標準が存在しなければいけないのかが明らかになる、というものがあります。後からチームに参画するメンバーのことを考えると、これは非常に大きな恩恵があります。

加えて私は、標準・ルールを適用したり変更するためのプロトコルが明確である、という恩恵も同じくらいあると感じています。現在の開発スタイルだったりアーキテクチャに怪しさを感じていたり危機感を持っていても、それを変更するためのプロトコルが明確でない場合、どうしても対応が後手に回るものです。

近い話で、ADR導入の少しあとで始めた「技術的意思決定会」という取り組みも似た効力を発揮しています。これは、技術的な意思決定権を持ったCTOであるishkawaがオーナーとなり、技術的な相談や意思決定を行う、という会議体です。毎週開催され、メンバーが意思決定したいこと・意思決定まではいかないけど相談したいトピックを登録しておき、関心あるメンバーとCTOが議論し、技術的な意思決定をします。

ここでの議論内容がADRとして起票される、という流れになることが最近は多いです。いきなりADRを起票しても良いのですが、事前に同期的に会話可能な場所で相談と合意を経ることができることから、技術的な意思決定に関わる敷居を下げられているのではないかと思います。

このように、決定があとから閲覧可能なものとして残っているだけでなく、アーキテクチャや技術的な方針をどこで相談しどう適用すればよいのかが明らかである、プロトコルが定まっている、というが非常に重要なことではないかと思います。

ADRを導入したのは2023年の1月なので、Stailerの開発開始から約2年と少し後ということになります。これまでの間も技術的な意思決定は10Xの中で多くなされてきましたが、もっと早くこうした仕組みがあれば、早く意思決定を行い良い変化をプロダクトにもたらすことができた可能性はあるな、と思います。これらも少なくとも開発開始から1年後くらいの段階では、軽量でも良いので取り入れていてもよかったのではないかと思います。

シフトレフト化によるQAプロセスの改善

これは、品質管理部の仲間たちが推し勧めてくれた大きな成果です。従来、Stailerの開発はで完成した仕様書をもとに品質管理チームのメンバーがテスト設計を作り、QAプロセスを実施する、という流れでした。

これを2022年7月ごろから、仕様書が確定する前に品質管理のメンバーが仕様書をレビューする、仕様書を作る前の時点から品質管理のメンバーが関わりフィードバックする、といったように徐々にシフトレフト(早期に問題発見する)という動きが進みました。

現在では品質管理チームのメンバーは開発チームの中に入って、仕様が定まる前の段階から仕様がどうあるべきかについてプロダクトマネージャーやソフトウェアエンジニア、デザイナーと一緒に議論を進めています。

これにより、リリース前のQAプロセスで発見されるバグ・あるいはリリース後に発生するインシデントの数を削減ことができました。リリースされたあとよりもリリースする前に問題を発見する方が、開発が完了したあとよりも開発が開始する前に問題を発見する方が、対応にかかるコストはずっと低くなります。

これは、先に挙げたDesing DocもADRも、ある種同じ話であるとも言えます。工程を悪戯に増やすのはプロダクトが立ち上がったばかりの状態では悪手とも思われますが、できるだけ早い工程で問題を発見し、改善するための手を打つことは、小さな組織でもスピードを上げることにつながります。

そういう意味で、これらの3つは仮に過去に戻れるならばまだプロダクトや開発組織の規模がより小さいときから導入したいな、と個人的には思えるものです。

早くやりすぎても成功しなかったかもな、と思うもの

一方で良い取り組みではあったものの、もっと早いタイミングでやったとしてもうまくいかなかっただろうな、と思うものもあるので、補足として紹介しておきます。それは、ドメインベースの開発体制への移行です。これはドメイン(業務)ごとにチームを分割するという組織設計上の試みで、2022年12月から検討を開始し2023年4月に実施しました。

振り返ればStailerというシステムが扱う業務の領域が幅広いこともあり、扱っている業務とシステムの解像度が高まり、朧げにでもどういうドメインの切り方が存在しているのかが明らかになって来たのが2022年半ばのことでした。

Stailerの開発を開始した2019年時点ではStailerの扱う業務の全体像を見通すことは非常に困難だったし、開発開始から1年が経過したタイミングでもまだプロダクトも事業も大きく変化している最中で同様、業務の全体像や業務ごとの関連を見通すのは困難な状況でした。

あまりに早い段階でこうしたチーム構造をとることや、それに応じてドメイン理解が浅い状態でチームごとにモジュール化を進めることは、おそらく混乱や手戻りを生んだだろうなと個人的には思います。

この移行の意思決定を行なった時点では、チームの認知負荷は増大しており、またコードのオーナーシップも持ちづらい状態ではあったのでギリギリとも言えますが、前述の理由から例えばこれをあまりに早くやったとしてもあまり幸せな結果にはならなかったのではないかと思います。

終わりに

ここまで読んでいただき、ありがとうございました。開発に関して必要となる制約やプロセスは、事業の状況やチーム状況に応じて変わるもので、少なければいいというものでも多ければ良いというものでもないのが難しいところだなと思います。

10Xでもこれからまた状況が変わるにつれて、無くなる制約もあれば加わる制約もあると思います。この記事を読んで、自身のプロダクトや組織にはいつどんな制約やプロセスを設けると良いかな、と思いを馳せていただければ幸いです。

続けていたことをやめること、新しいことをはじめること

この記事は🎄10X プロダクトアドベントカレンダー2023の20日目の記事です。

19日目の昨日はogaさんによる「プロダクトチームとCSの連携のお話」でした。


こんにちは、品質管理部のtarappoです。

2023年も終わりですね。

唐突ですが、はじめたことをやめることってむずかしかったりしませんか? はじめたときには目的があったものの、気づいたら惰性で続けてたりしませんか?

1年も終わりが見えてきて「大掃除だ」「棚卸しだ」と動いてたりすると思うので、今日はそのような話にフォーカスしたいと思います。

品質管理部がおこなっているメイン以外のタスク

メインでおこなっているタスクについてフォーカスして話すのもよいのですが、文量が長くなりそうなのでメイン以外のタスクについて話していきたいと思います。 品質管理部ではメインとなるタスク以外にもいろいろなことをおこなっています。

例えば、次のようなものを定期的におこなっています*1

  • 入社時の品管主催のオンボーディング
  • 品管週報

これらは当然、目的があってはじめたものです。

はじめたころから時間が流れていくと、当初の狙った目的が達成できていたり、その目的を達成するにはこのアプローチは異なるといったことが起きてきます。 そういった中で、現状を元に続けるべきかどうかを定期的に考えていますしメンバーからFBをもらうこともあります。

はじめたものは惰性で続けてしまいがちではありますが、これらにはメンバーの時間を一定使っています。 そのまま継続することは関係する人々にとっての時間の無駄使いにもなってしまいますし、見直すことは重要です。

この1年の間にやめる選択をしたもの

この1年間の間に、品質管理部でやめたこととして次のようなものがあります。

  • ドヤ会
  • 品管週報

それぞれには次のような目的がありました。

名前 内容 目的
ドヤ会 部内でメンバーのドヤ!とした出来事を共有する会 だれがなにをおこなったかをチーム間で共有(チームビルディングが目的)
品管週報 週1回、品管メンバーがおこなったことを全体に共有する報告書 品管がどういったことを行なっているか部外の人に知ってもらう(品管の認知向上が目的)

かんたんな目的は上記に記載したとおりです。 もう少しそれぞれについて詳しく次に記載します。

ドヤ会

ドヤ会においては、部内のメンバーの交流の一環としておこなっていました。 誰がどういったことをおこなったかというのをメンバー間で共有する場を用意することで「それいいね」と気づいてもらいやすくするというのもありました。

実際におこなっていた期間は約8ヶ月ほどになります。

それだけの期間がたつと、上述した役割の必要性がなくなったと判断し終了することとなりました。

品管週報

品管週報においては私が入社したタイミングで認知向上の目的でどういったことをおこなっているかをアナウンスするためにはじめたものです。

まだチーム*2が出来て日も浅くどういったことをしているのかというのが知られてないというのがありました。 また、今みたいにチームに入って動いていたわけではなかったため何をいまおこなっているのかというのも分かりづらいというのもありました。

次のような形でNotionに毎週週報を作って全体にSlackで共有していました。

最初にやったこととして次のブログ記事にも書きました。

この品管週報は、金曜日に週1回出し続けて次のVol.80が最終号となります。

最近は次のようなコンテンツで出していました。

コンテンツの内容はたまに見直しし更新はしていましたが、80号ともなると惰性感は出てきていました。 また、開発チーム体制になってからはチームに品管メンバーが必ずいるため当初の目的である認知度向上は達成できただろうということでやめることとしました。

残された課題とその先

上述したものについては、目的の多くは達成したことからやめたわけですが、全てではありません。 従って、残された課題はあります。

品管週報においては「認知度向上」が目的でした。 まずは品質管理部というものを知ってもらうというのがありました。

知ってもらう必要性はなぜか?というと「全員で品質を作っていく」ための第一歩とするためです。 「認知」されなくてはその先の「協業」はありません。

そのため残された課題は、本来の大きな目的に対してどういったアプローチが必要かということになります。

新しいことをはじめる

上述したように残された課題はあります。 従って、その課題を解決するという目的にフォーカスした新しいことを2024年からはじめる予定です。

新しいことをはじめたとしても、それが目的からずれてしまったり、達成したのであれば見直しは必要です。 それを肝に命じながら2024年も、また新しいことを「恐れずに」いろいろとやっていこうと思います。

おわりに

今回は品質管理部がおこなっているメイン以外のタスクについて話しましたが、メインのタスクにおいても同様です。 継続し続けることが必ずしも正しいとはかぎりません。

継続は大事ですが、いつしか惰性となってしまうこともあります。 そして、はじめることよりも止めることの意思決定のほうが大変だったりします。

しかしやめることは大事です。

2023年の1年間で品質管理部もだいぶ変化しました。 その中で取り組んできたことをやめたり、新しいことをはじめたりとしています。

2024年はどういったことを進めるのか、2023年度はどうだったのかについてはまた数カ月後にブログ記事にかければと思います。

*1:メインとなるタスク含め定期的におこなっているものはリスト化しており、定期的に棚卸しをしています

*2:入社当時は品質管理部ではなくQAチームという形でした

10XでProduct Fridayという社内発表会を運営している話

この記事は🎄10X プロダクトアドベントカレンダー2023 の17日目の記事です。

16日目の昨日はkazk1018さんによる「Data as a Product」について考える でした。

こんにちは、10XでProduct Managerをやっておりますkeiです。本日は10Xで行っているProduct Fridayという取り組みについてご紹介します。

Product Fridayとは

もともと「開発共有会」という名の開発で共有した知識により全体のパフォーマンスがあがるものを定期的に共有できる場があり、エンジニアリング本部(SWEやQAを中心とした組織)により運営されていました。それをこの4月からプロダクト本部(PdMやDesigner, データプロダクト)と合同で運営することとなり、趣旨は引き継ぎつつ職種を超えて(主に開発に関わる)知見を共有すること、コミュニケーションを促進すること、発信カルチャーを醸成することを目的に開催しています。

  • 頻度は隔週金曜の16-17時
  • 1枠15分くらいで最大3名の発表(短くても可)、形式は自由
  • 立候補制(ローテとかではない)
  • Audienceの参加は自由、おやつ代の補助あり

Happy Friday的なカジュアルな意味合いも込めてProduct Fridayと命名しました。4/28に第1回を開催してからもうすぐ開催される12/22まで延べ15回、計45の発表がありました。

実際にあった発表例

  • UIとUXの話をしよう - デザイナー採用面接でのWSをやってみる -
    • FigJamを使ってその場で仮想サービスへのツッコミと質疑をやってみるというインタラクティブな発表で、大変盛り上がりました
  • PdM×デザイナコラボでモブ業務フロー一緒にやったらとても良かった話
    • PdM x Designerでラジオ風に業務フローを作ってみる(再現)という斬新な発表で、質問もおハガキ紹介という徹底ぶりでした
  • お届けチームのダッシュボードを作った話
    • パートナー毎のシステムメトリクスや生産性、リリースした機能がどう使われているか?開発スプリントの可視化まで、いかに「定期的に見られる」ダッシュボードを構築するかという観点で非常に参考になりました

やってて良いと感じること

知見の共有

まずは趣旨どおり、10Xに在籍する各種メンバーから知見を共有してもらえるのが良きポイントで、アンケートでも「SWE以外の方の発表を聞けるのが新しい気づきがあってよい」や「他のチームの知見がたくさん聞けて学びが多い」といった感想が集まっています。

コミュニケーションの促進

また、新入社員のメンバーには自己紹介LTをしてもらっており、As-One Mtgという全社定例での自己紹介もありつつ(5分)、より深い自己紹介をプロダクトに関わるメンバーにできることで業務上話す際にもアイスブレイクに繋がっているようです。

運営の流れと難しさ

運営は私を含む3名で行っており、週にかける時間は30分程度というイメージです。開催〜次回までの運営の流れでいうとざっくりこんな感じです。

  • 事前準備
    • 発表者への準備リマインド
  • 当日
    • BGMを流す(Youtube)
    • 録画をする
    • Product FridayのSlackチャンネルでワイワイを促す
    • 積極的に質問をする
    • おわりにアンケートを案内する
  • 次回に向けて
    • 開催翌週の火曜に30分の運営定例を実施
    • KPTしたり次回までのToDoを確認する

難しさとして感じるのは大きく2点で、これからも課題だなと感じています。

1. コンテンツの安定提供

コンテンツを安定的に提供するためにはコンスタントに発表者が集うことが必要なわけですが、立候補にも波がありコンテンツが少なくなってきたときは運営が声掛けを頑張っています。

普段の業務の中でも「これProduct Fridayで発表してみよう」「これはProduct Fridayで聞いてみたい!」みたいな会話が運営を介さずとも自然に発生するような状態が理想かなと思っています。

2. 発表しやすい空気づくり

回を重ねていくと発表のリピーターも出てくるため、発表者のUXは大変重要です。当日の運営としてもチャンネルを盛り上げたり、なるべく質問をしたりするものの、リアクションが見えにくかったという声もあったり課題に感じています。

運営だけでなく空気は参加者みんなで作るものなので、なるべくビデオOnにしたりリアクションを送ったり(10XではGoogle Meetを使っています)、気軽に発表できる空気をつくっていきたいです。

おわりに

最後までお読みいただきありがとうございました!プロダクト組織に所属されている方の参考になれば幸いです。

明日18日目はむらなかさんによる「データ分析はプロダクトの機能の一部である」の予定です!お楽しみに!

SREとして入社し1年たつので振り返り

こんにちは。SREの栗原です。 この記事は10Xアドベントカレンダーの15日目の記事です。

私がSREとして2022年の10月に入社し1年が経ちました。 この1年間でやってきたことについて書いていきます。 現在SREチームは採用募集中です。この記事を見てスキルがマッチしていたり興味が湧いた方は是非カジュアル面談をしましょう!

SRE(Site Reliability Engineer) / 株式会社10X

  • 入社初期の取り組み
  • 自動化と効率化への取り組み
    • Terraform moduleへのresource追加
    • Redashやめる
    • Kubernetes yamlのコピペ運用をやめる
    • サービスアカウントキーの発行方法の見直し
  • 育休の取得
  • その後の取り組み
    • Deny policiesの導入
    • Terraform Planの権限修正
  • これから
続きを読む

GitHubの監査ログを定期的にexportして保存する

こんにちは。セキュリティチームでソフトウェアエンジニアをしてる@sota1235です。

この記事は10Xアドベントカレンダーの13日目の記事です。

www.notion.so

昨日の記事はSuzuki Ryotaさんのお届けチームでオーナーシップを持っていくぞでした!

今回はGitHubの監査ログを定期的にexportし、保存する仕組みを作った話をします。

  • 監査ログとは
  • GitHubの監査ログ
    • GitHubの監査ログは永久には保存されない
    • 監査ログの出力方法
    • この記事の本題
  • 監査ログ出力の仕組み
    • ざっくり要件
    • 技術選定
      • ログの保存場所
      • ログの取得処理
      • ログの取得・保存処理はGitHub Actionsで行う
    • 全体像
      • 1. BigQueryに最新データを取得しに行く
      • 2. 監査ログを取得する
      • 3. 監査ログを保存する
    • 権限管理
      • 監査ログに含まれるデータについて考える
      • 具体的にどこに制限をつけるか
    • 今後の活用方法
  • 最後に
  • 明日は
続きを読む

Relay Proxyを活用してLaunchDarklyを導入する

Relay Proxyを活用してLaunchDarklyを導入する

はじめに

この記事は 10X アドベントカレンダー2023 11日目の記事です。

前日の記事は id:hisaichi5518 さんによる「“10xを創る”開発チーム文化とはなにか 〜お届けチーム編〜」でした。


こんにちは、今年の6月に10Xに入社して今はお届けチームでソフトウェアエンジニアをしているgenkey6です。

この記事では、お届けチームで直近取り組んでいるfeature flag管理サービスのLaunchDarkly導入に関する話をお届けします。

10XではServer Sideの開発言語としてDartを採用していますが、feature flag管理サービスを導入するにあたってServer Side DartのSDKやライブラリを公式で提供しているサービスがなく苦戦しました。

最終的に採用したLaunchDarklyでは、SDKこそ存在しないもののRelay Proxyの活用という選択肢をとることで公式がサポートする方法でServer Sideからサービスを利用することができました。

LaunchDarklyがSDKでサポートしている開発言語は非常に充実しているためこうした対応が必要になるケースは稀だと思いますが、まだ見ぬ未来のLaunchDarklyユーザーに向けて、導入にあたって検討した内容やハマったポイント等をまとめておきます。

ニッチな内容ですが最後までぜひお付き合いください!

導入の背景

大変ありがたいことに、10Xが提供しているStailerのプラットフォームを活用してネットスーパー/ネットドラッグストア事業を運営されるパートナーの数は日々増えており、併せてお届けチームで開発している小売事業者向けのスタッフアプリや管理画面を利用するユーザーも増加しています。

これらのアプリケーションの特徴として、ユーザーである現場スタッフの方々の業務時間中はほぼ常時アプリケーションを使用している状態になるため、高い信頼性が求められるという点があります。

また、開発している機能に占めるCUJ (Critical User Journey) の割合が大きいため、特定の機能に障害が発生すると業務のブロッカーとなる上、最悪の場合はエンドユーザーであるネットスーパー/ネットドラッグストアのお客様のサービス利用体験にも影響が出てしまいます。ゆえに、毎回のリリースに対して慎重な姿勢を取らざるを得ないという状態にありました。

一方で、現場のオペレーション効率化にアプリケーションが寄与できる余地はまだまだ残されているため、なるべく細かくリリースを行なってインクリメンタルに改善を行なっていきたいというニーズも存在します。

こうした背景から、信頼性の担保と開発速度の向上を両立する手段として、feature flagを活用してリリースの影響範囲を抑えつつ障害発生時の復旧時間を短縮することを目指した検討が始まりました。

LaunchDarklyについて

前提として、feature flagの仕組み自体は単純なものなので、これまでの開発でも各所で利用していました。

具体的にはアプリケーションの実装内にflagをハードコーディングする方法や、環境変数 (もしくはそれに準ずる設定ファイル) を用いて機能のon/offを切り替える方法が現在進行形で利用されています。

こうした素朴な実装でもやりたいことは部分的に実現できますが、

  • 影響範囲を抑えるために一部のユーザーに限定したリリースを行うための仕組みが欲しい (単純なユーザーidによる指定に加えて、ユーザーが所属するパートナーや店舗といった単位も想定)
  • 障害発生時の復旧時間を可能な限り圧縮するために、flagの値を更新する際はデプロイを不要としたい
  • これらの仕組みを自前で実装・保守するコストはできるだけ払いたくない

といった理由により、はじめからSaaSを導入できないか検討しました。

ここでは世の中に数多く存在するfeature flag管理サービスの詳細な比較 *1 は行いませんが、LaunchDarklyを採用した理由については簡単に触れておきます。

調査を進めていくと、冒頭で述べたようにServer Side Dartで利用できるSDKを公式にサポートしているサービスが存在しないという壁にぶつかりました。

サービスによってはSDK自体は必ずしも必要ではなく、用意されているエンドポイントにリクエストを送るだけで済むようなものも存在しましたが、flagの値をなるべくリアルタイムに更新したいことを考えると何かしらstreamingな形でサービスとやり取りを行う仕組みは欲しいところです。

そんな中で、LaunchDarklyではRelay Proxyというコンポーネントが間に立ってサービス本体とのstreaming通信を肩代わりしつつスケーラブルなアーキテクチャを用意してくれる、かつこのRelay Proxyは公式がサポートするOSSとして提供されていることから、最有力な選択肢として残りました。

加えて、同時に導入を進める予定のモバイルアプリで利用できるFlutter向けのClient SDKが存在する点や、既に開発の中で利用していた各種ツールとのインテグレーションが充実している点などから活用イメージがつきやすかったことが決め手となり、採用に踏み切りました。

Relay Proxyについて

Relay Proxyとは

LaunchDarklyは公式ドキュメントが非常に充実していますが、Relay Proxyについては例えば以下のページにまとまっています。

docs.launchdarkly.com

また、以下ではSDKが存在しない言語でLaunchDarklyを利用する際に選択できるオプションの1つとしてRelay Proxyが紹介されています。

docs.launchdarkly.com

これらのページに書かれている内容を総合すると、

  • Relay ProxyはGoで実装されたマイクロサービスで、LaunchDarklyのstreaming APIと通信を行ってflagの値を保持する
  • ユーザーはLaunchDarklyと直接通信する代わりにRelay Proxyにリクエストを送るようにすることで、LaunchDarkly側に大量のリクエストが飛んでしまうのを防げる
  • SDKのない言語でLaunchDarklyを利用する方法は他にも存在し、例えば既存のSDKのラッパーを実装する方法や自前でSDKを実装する方法 *2 が紹介されている

といったことが分かります。

Relay Proxyは元々は負荷分散を想定した仕組みですが、言語非依存かつ独立してスケール可能なコンポーネントを実装コストを抑えつつ用意できるため、今回のユースケースにぴったりと当てはまるというわけです。

Relay Proxyの設定を決める

さて、Relay Proxyが目的に適していることが分かったので、続いてはRelay Proxyの設定について考えていきます。

この項の記述は主に公式ドキュメントの以下のページで触れられている内容に基づいているので、実際に導入を検討される場合は一度目を通すことをおすすめします。 (なお、Relay Proxyのバージョンは執筆時点で社内で利用されているv8.2.0を前提とします)

docs.launchdarkly.com docs.launchdarkly.com

最初に決めるべきはRelay Proxyのmodeです。Relay Proxyには proxy modeとdaemon modeという2つのmodeが存在します。両者の大きな違いは、LaunchDarklyと通信して手に入れたflagの値をどこに保存するかです。

proxy modeではflagの値をインメモリなキャッシュとして保持するのに対し、daemon modeではpersistent storeと呼ばれるデータベースに保存します。 (persistent storeの実装にはRedisやDynamoDBが用いられます)

ドキュメントの記述によると、We generally recommend configuring your SDKs for proxy mode. Daemon mode is a workaround for environments where normal operation is not possible. とのことなので、今回はproxy modeを採用することにしました。*3

他に試せていない内容として、proxy modeとpersistent storeを組み合わせて使うケースも存在します。具体的には、LaunchDarklyのBig Segmentsという機能を利用する場合はpersistent storeを利用することが推奨されていますが、今回のユースケースには当てはまらなかったため検討対象から外しました。

もう1つのポイントは、Relay Proxyのスケール数です。(StailerのインフラではKubernetesを採用しているため、ここでのスケール数とはRelay Proxyをデプロイする際のPodのreplica数を指します)

公式ドキュメントのScaling guidelinesには、We recommend you provision the Relay Proxy the same way you would an HTTPS proxy, and plan for at least twice the number of concurrent connections you expect to see. と記載されていたため、Relay ProxyにアクセスするServerコンポーネントに対するHTTP Proxyで設定しているreplica数に揃える形で設定することにしました。

また、オートスケールの設定については最初はリクエスト数が少ない箇所から運用を開始することを想定して、一旦は見送っています。

今回の取り組みと並行して、DatadogのメトリクスによるHPA (Horizontal Pod Autoscaler) の設定を可能にする仕組みをSREチームに用意してもらったので、今後のリクエスト数の実績値を元に導入を検討していく予定です。

Relay Proxyをデプロイする

設定の方針が決まったので、続いてはRelay Proxyを実際にデプロイするステップです。

以下のページで複数のデプロイ方式が紹介されていますが、社内で既にHelmを活用していたためそちらを使うことにしました。

docs.launchdarkly.com

公式のHelm chartが以下のrepositoryで管理されているため、repository内のドキュメントを参考にしつつvalues.yamlの中身を埋めていきます。

github.com

各種configurationの項目の意味合いについては以下にまとまっているため適宜参照しつつ、

以下のファイルで記述されているデフォルト値を更新する形でvalues.yamlを記述すればOKです。

10Xではこうして用意した設定に基づいて、Helmfileなどの仕組みを活用しつつKubernetesのマニフェストを生成してデプロイしています。

Relay Proxyを監視する

Relay Proxyがダウンしてしまうとアプリケーション側でLaunchDarklyのfeature flagの値に依存している箇所は全てデフォルト値にfallbackされてしまうため、運用開始後の監視は厚めに設定しています。

監視内容の設計にあたっては公式ドキュメントの以下のページが参考になりました。

docs.launchdarkly.com

上記を参考にしつつ、10Xでは次に挙げるような項目を監視しています。

  • Podの死活監視
    • (デプロイ時の設定で無効化していなければ) PodのlivenessProbe/readinessProbeがRelay Proxyの /status エンドポイントにリクエストを送るように設定されているため、これをhealth checkとして利用しています
  • LaunchDarklyとの接続が正常かどうかの監視
    • /status エンドポイントのresponseにはLaunchDarklyとのstreaming通信が正常に行われているかどうかを示す情報が含まれます (JSONPathで書くと $.environments.NameOfEnvironment.status の部分)
    • これをDatadogのSynthetics Testを用いて定期的に確認することで、通信が途絶えた場合にアラートを出すようにしています
  • Relay Proxyのパフォーマンス
  • Relay Proxyにリクエストを行うClientがflagの評価に失敗した際に出力するログ
    • 必ずしも全てのケースで緊急の対応が必要なわけではありませんが、flag評価に失敗してfallback値が使われたことは検知したいため、Cloud Loggingのlog-based alertsを用いた通知を行っています

Relay Proxyにリクエストする

ここまででRelay Proxyを利用する準備が整ったため、いよいよServer SideからRelay ProxyにリクエストできるようにDartでClientを実装していきます。

大まかな方針としてはflag評価用のエンドポイントに対して、Contexts *4 の情報を付与してリクエストするだけのシンプルなものになります。

以下で、実装時にハマった点をいくつか取り上げておきます。

  • undocumentedな仕様が多い
    • requestで渡すべきContextの型、特に複数のContextを組み合わせるMulti-contextsの場合の情報が記載されておらず、最終的にRelay Proxy本体とテストの実装を読んで理解しました
    • また、responseの型についても明示されておらず、手元でAPIを呼び出してresponseの内容を直接確認する必要がありました
  • 同じくDartで実装されているFlutter向けのSDKと型を共有できそうで出来ない
    • Contextの型 (上記で確認したもの) が実は違います
    • packageをそのまま追加するとFlutterまで依存に入ってきてしまうため、実際に参照する型定義だけをコピペする必要がありました
    • 最初はClient実装に関わる型定義部分はほとんど流用できるか?と考えてチャレンジしてみましたが、結果的に正しく使い回せたのは LDValue というflagの値に関する型定義のみでした

これより詳細な実装の中身に関してはここでは立ち入りませんが、以下のrepositoryにて社内で利用しているものとほぼ同じ実装を行っているので、気になった方はご参照ください。

github.com

今後に向けて

以上、Relay Proxyを活用してSDKのない言語でLaunchDarklyを導入するまでの道のりについて書いてきました。

導入してからまだ日は浅いですが、チーム内では既に以下のようなユースケースでLaunchDarklyを活用し始めています。

  • 細かな調整が求められるUX改善タスクにおけるExperimental Flag
  • 比較的長期にわたって行われるリアーキテクチャプロジェクトにおけるMigration Flag

また、将来的には次のようなユースケースにも活用の幅を広げていきたいと考えています。

  • 特定の機能を限られたユーザーに提供する際のPermission Flag
  • 外部サービスに依存している箇所のKill Switch
  • Firebase Remote Configを利用してA/Bテストを実施しているケースの代替

加えて、今回の記事では触れられませんでしたが、LaunchDarklyの運用面の整備として以下のような取り組みも並行して進めています。

  • flagの負債化を防ぐ仕組み
  • ソフトウェアエンジニア以外がflagの値を安全に変更できるような仕組み
  • 複数チームで利用する際のガバナンスの仕組み (flagの命名規則やflagに付与するTagsのルールなど)

活用が進んでいった暁にはこれらのテーマでもまた記事を書いてみたいです。

終わりに

この記事では信頼性の担保と開発速度の向上を両立する手段としてのfeature flagについて紹介しましたが、直近では同様のゴールに対して次のような施策も検証されています。

  • リリースの安全性を高めるProgressive Deliveryの仕組み
  • モバイルアプリにおけるhotfixリリースを容易にするためのOTAの仕組み

10Xでは、こうした取り組みを一緒に進めてくれるソフトウェアエンジニア、SREの仲間を募集しています!

open.talentio.com open.talentio.com


最後に、筆者が所属しているお届けチームの取り組みについて、他のメンバーが書いた以下の記事も併せてご覧ください。

続く明日の記事もお届けチーム所属のsuzukiさんによる「お届けチームでオーナーシップを持っていくぞ」です。お楽しみに!

*1:先日Findyさんが主催で開催されたイベントの次の登壇資料に網羅的にまとまっているため、サービス選定に悩まれている方は参考にされると良いと思います: https://speakerdeck.com/gunta/uxno-ding-dian-devcycle-ni-chan-rizhao-kumadenodao-nori

*2:ただし、いずれも公式としてはサポート外ですよという注意書きがされています

*3:じゃあいつdaemon modeを利用すべきなの?かというと、同じドキュメントで Daemon mode requires that you configure server-side LaunchDarkly SDKs to communicate directly with they Relay Proxy's persistent data store. We recommend this configuration when you're using LaunchDarkly with PHP or in a serverless environment. と書かれています

*4:「ユーザー」を拡張した概念で、リクエストを行った主体が、事前に設定した条件に合致するかどうかを判断するためのkey-value形式の属性

“10xを創る”開発チームの文化とはなにか 〜お届けチーム編〜

この記事は 10X アドベントカレンダー2023 の10日目(12/10)の記事です。9日目(12/9)の昨日は、 id:takanamito さんによる「grpc-dartのInterceptorを使う」でした。

10Xのお届けチーム エンジニアリングマネージャー(以下, EM)の id:hisaichi5518です。10Xではソフトウェアエンジニアとしてサーバサイド、Android、iOS、Flutterと色々やってきて、今は「人を動かして、ことを成す」を目指してEMとして活動しています。

今回は、自分が担当しているお届けチームについて「どんな雰囲気なのか」「どういうチームを目指しているのか」「具体的な活動」について書いていこうかなと思います。書き終わって気付いたんですが、今年のテーマは"開発・プロダクト"らしく、ちょっとテーマに沿ってない感があるけどまあいいかってなりました。人生ってそんなもんですよね

お届けチームって?

10Xは、”10xを創る”というミッションを持っていますが、お届けチームは、Stailer*1において"パートナーが、かんたんに届けられる仕組みを提供する"をミッションに持つチームです。このミッションを達成することが10xを創ることとも言えると思います。

イメージしやすいようにどういう機能の開発をしているのか具体の話をすると、店舗スタッフが商品を取ったことを記録するといった機能や配達スタッフが配達時にどの順番で届けるかといった機能などを提供するアプリの開発をしているチームです。

また、お届けチームは執筆時点で、EM1名、SWE4名、QA3名、Designer1名、PdM1名の計10名で構成されています。

お届けチームの雰囲気「楽しく働く」

カジュアル面談をしていると10Xはあんまり雑談がない雰囲気と思われていたりしますが、お届けチームのSlackチャンネルでは、こんな改善した!やこうしたほうがいいかも?や気になった技術ブログの話みたいな仕事に関連する話はもちろん、アニメの話や今日のお昼ごはんの話といった仕事に関係ない雑談もよくしています。他にもSlackのHuddleで作業している人同士で繋げたり雑談をすることもあります。

CIが爆速に!!

スクラムイベントの改善の提案

やいていき!

これは、チームメンバーの根幹に"楽しく働こう!"があると思っていて、それがチームの雰囲気にも出ていると自分は思っています。

お届けチームはどういうチームを目指すのか

もちろん楽しく働くのは大事ですが、それだけではお届けチームの"パートナーが、かんたんに届けられる仕組みを提供する"というミッションは達成出来ません。23年4月からお届けチームは組成*2されたのですが、その時からお届けチームはどういうチームを目指すのかを定義しています。

10Xでは、10X Valuesという価値観を定義していて、それを元に作成されています。

1. 中長期的な観点を持った活動が継続的に行われている

なぜ目指すのか

ある機能を期日に間に合わせるように作るというのは短期的には非常に重要ですが、期日に合わせようと無理をした実装になりバグの温床になったり、作った本人しかわからない機能になったり、後から色々とツラミが出てきます。そうならないためには、中長期的な観点を持って実装面や機能面はどうあるべきかを考え、それを言語化し、一歩ずつ実現する必要があると考えています。

2. チームが自分たちで判断し実行している

なぜ目指すのか

お届けチームは、経営や他事業部から言われたことをただやるチームではなく自分たちで判断して実行するチームでありたいと思っています。そのほうがメンバーがやることに対して自分ごと化出来て成果が出せると考えています。

3. チームで成果を出し、チームで評価される

なぜ目指すのか

“10xを創る”という大きな成果を出すには、1人1人が頑張って成果を出してその総和で勝負するのではなく、チームで成果を出すことで個々の総和をチームで超える必要があります。そのためには、メンバー同士が助けを求め、助け合うことで大きな成果が出せると考えています。

具体的なお届けチームの活動の例

お届けチームがどういうチームを目指すのかはわかったと思うので、それを踏まえて具体的にどういう活動をしているのかの例をこのセクションでは記載します。これは、EMの自分だけがやっているのではなく、メンバーが行っていることです。

理想の姿とギャップをドキュメントにして、チームで取り組む

中長期的な観点を持った活動は、まず理想の姿を定義して現状とのギャップを埋めるために着実に進めることが重要です。そして、一歩ずつ進めるためには1人で実施するのではなく周りを巻き込み、チームとして取り組む必要があります。そのためにはドキュメントを作成して、他の人も理解できるようにする必要があります。

最近作成されたドキュメントは以下のようなものがあります。(一部伏せ字にしています)

  • feature flagの削除を忘れないようにするための運用
  • お届けチームがオーナーシップを持つコンポーネントの監視・オブザーバビリティのあるべきを考える
  • 滞留しているプルリクエストを消化するためにやること
  • 満足のいく引き継ぎってなに?
  • ******* Syncerの現在地と目指しているところと未来
  • 総量ピックへのpick-packモジュール導入

現場リサーチ

お届けチームでは、ネットスーパーを運営する実店舗にお伺いしオペレーションを観察することを現場リサーチと呼んでいます。この現場リサーチを行うことで、”パートナーが、かんたんに届けられる仕組みを提供する"を実現するための課題やあるべき姿を考え、チームで何をやるべきかを判断し実行できるようにしています。

現場リサーチについては、お届けチームのPdMであるkoichi-mさんが12/9に公開した より良いオペレーションのためのプロダクトとは?お届けチームが探索する「現場リサーチ」〜プロローグ〜|こういち / koichi-m にも記載されているので、読んでみてください。

目標共有会

10Xでは個人の目標設定を半期ごとに行っています。目標自体は一覧として共有されるのですが、それだけだと目標設定時に何を考えたのか、どういう思いがあるのかなどがわかりません。

チームで成果を出すには、各個人がどういうことを考え目標を設定したのかや助けてほしいことなどをチームで共有し、職種関係なく助け合える状態になることが必要があると考え、お届けチームでは目標共有会を行っています。

目標共有会では、以下のようなことをチームで話しました。

  • この半期で達成したい目標
  • 実は持っている裏テーマ
  • メンバーに知っておいてほしいこと
  • 職種限らず、達成するために助けてほしいこと
  • メンバーからの質問/感想タイム

まとめ

お届けチームの雰囲気や目指したい形、具体的に何をやっているのかを紹介しました。

ここでは書ききれなかった「ミッションの”かんたん”って何?どういう挑戦がある?」「お届けチームは具体どういう開発をしているの?」「これらを実現するためにEMはどう振る舞っているの?」などもっと詳しく知りたい人は、XのDM/リプライまたはカジュアル面談フォームからどうぞ。

明日は、お届けチームメンバーの id:genkey66 さんによる「Relay Proxyを活用してLaunchDarklyを導入する」です。楽しみですね!

関連

*1:ネットスーパー・ネットドラッグストアの立ち上げと成長を支援するサービスです

*2:ちなみに組成された経緯は、ドメインベースの開発体制への移行 - 10X Product Blogで読めます。