Firebase Authenticationにおける分散トランザクション

はじめに

2024年4月に株式会社プレックスにエンジニアとして新卒入社した佐藤祐飛と申します。現在はサクミルという建設業界向けのSaaSプロダクト開発を行っています。

sakumiru.jp

Firebase Authentication(以下Firebaseと略します)を利用した認証において、ユーザー作成時に分散トランザクションによってデータの整合性を担保する実装をRuby on Railsで行ったのでその知見について共有したいと思います。

firebase.google.com

背景

サクミルにおけるユーザー認証について

サクミルではFirebaseを活用したJWTによるユーザー認証を行なっています。ユーザー認証完了後、FirebaseのユーザーUIDを元にサクミルはDB上にあるユーザーデータを提供し、各ユーザーはサクミルにログインすることができます。

ユーザー作成方法について

サクミル管理画面ではアカウント発行機能としてFirebase上へのユーザー作成とサクミルのDB上へのユーザー作成を同時に行う機能を提供しています。サクミル管理画面のAPIにおけるユーザー作成手順を以下に示します。

ユーザー作成手順

サクミル管理画面のAPIRuby on Railsで書かれているのですが、Firebase公式からはRubySDKが提供されていないので、google-api-ruby-clientというgemを活用して、Firebase上へのユーザー作成を行なっております。

github.com

課題

ユーザーデータの不整合が生じる可能性がある

ユーザーデータがDBとFirebaseという異なる2つのノードに保存されるので、データの不整合が生じる可能性があります。

例えば、Aさんのユーザーデータを作成することを考えます。Firebase上へAさんのユーザーデータを保存することに成功したものの、その後のサクミルのDB上への保存が何らかの原因で失敗した場合、「サクミルDBにはAさんのデータがなく、FirebaseにはAさんのデータがある」という不整合が発生します。

ユーザーデータの不整合が生じる例

この不整合の状態で、再度サクミル管理画面からAさんのアカウント発行を実行するとFirebase上の一意制約によってアカウント発行の処理が失敗してしまいます。

Firebaseのコミット制御やロールバックができない

いわゆるIDaaSであるFirebaseを利用すると、認証サービスの実装コストや監視コストが下がるというメリットがある反面、デメリットとして認証サービスのカスタマイズ性が低下します。

FirebaseはFirebase内部のDBについて、コミットのタイミング制御やロールバックを行う機能を提供していないので、分散トランザクションの代表的手法である2フェーズコミット(2PC)を行うことができません。

サーガパターンによる整合性担保

上記の課題を解決するために、サーガパターンによる分散トランザクション管理を実装しました。

サーガパターンとは

サーガパターンとは、複数のサービスにまたがるビジネスプロセスを管理し、データの整合性を担保する分散トランザクション手法です。サーガパターンは、各サービスのローカルトランザクションのシーケンスであり、ローカルトランザクションはDBを更新して、次のローカルトランザクションをトリガーします。

ロールバックを実行する場合は、各ローカルトランザクションを取り消す操作として補償トランザクションを実行します。

サクミル管理画面 APIの実装

Firebaseへの操作を管理するFirebaseAdminクラスを以下に示します。

工夫したポイントは2点あります。 1点目はFirebaseへの操作を行うメソッド(今回はsign_up_user)内で補償トランザクションをスタックに積んだことです。 2点目は、補償トランザクションの処理をproc インスタンスとしてスタックに保持させ、rollbackメソッドによってロールバックを行えるようにしたことです。

これらの工夫によって、動的にUIDが変化するロールバックの処理を実現することができます。

class FirebaseAdmin
  def initialize
    # HTTP通信のclientを初期化する
    @client = Google::Apis::IdentitytoolkitV3::IdentityToolkitService.new
    
     # 認証
    ...
    # 補償トランザクションの処理を保持するスタック
    @revert_proc_stack = []
  end

  def sign_up_user(email:, password:)
    # Firebaseへユーザー作成のリクエストを送信
    request = Google::Apis::IdentitytoolkitV3::SignupNewUserRequest.new(email:, password:)
    response = @client.signup_new_user(request)

    uid = response.local_id

    # ユーザー削除の処理(補償トランザクション)をスタックにプッシュする
    @revert_proc_stack.push(proc { delete_user(uid:) })

    uid
  end

  def delete_user(uid:)
    request = Google::Apis::IdentitytoolkitV3::DeleteAccountRequest.new(local_id: uid)
    @client.delete_account(request)
  end
  ...

  def rollback
    # スタックが空になるまで補償トランザクションを実行する
    until @revert_proc_stack.empty?
      proc = @revert_proc_stack.pop
      proc.call
    end
  end

  def cleanup
    @revert_proc_stack.clear
  end
end

以下に、アカウント発行を実行した際に叩かれるcreate_user!メソッドを示します。

工夫したポイントはActiveRecordトランザクション内でFirebaseへの操作とDBへの操作を実行し、例外処理でロールバックを行ったことです。例外(FirebaseまたはDBに対する処理の失敗を想定)が発生するとFirebase上のロールバック処理とDBのロールバック処理が実行されることが保証されるため、ユーザーデータの整合性が担保されます。

def create_user!(email:, password:)
  # FirebaseAdminインスタンスを作成
  client = FirebaseAdmin.new

  begin
    User.transaction do
      # Firebase上にユーザーを作成する
      uid = client.sign_up_user(email:, password:)

      # DB上にユーザーを作成する
      user_record = User.create!(..., email:, uid:)
      ...
      save!
    end
  rescue StandardError => e
    # 例外をキャッチし、ロールバックを実行する
    client.rollback
    raise(e)
  ensure
    # スタックのクリーンナップを必ず実行する
    client.cleanup
  end
  ...
end

最後に

プレックスではエンジニアを募集しております。ご興味ある方がいらっしゃれば是非連絡をください! dev.plex.co.jp

また、入社エントリを執筆いたしましたのでご覧いただけるととても嬉しいです!

product.plex.co.jp

【入社エントリ】効率化大好きなエンジニアがプレックスに入社した理由

はじめに

初めまして、エンジニアの山崎と申します。

2024年1月に株式会社プレックス(以下、プレックス)にコーポレートエンジニアとして中途入社いたしました。

入社してから半年弱経過した上で感じたプレックスの良さや業務内容をお伝えできたらと思います。

自己紹介

2020年に新卒で Amazon Web Service に入社し、CSE(クラウドサポートエンジニア)に従事しました。
しかし、人生の深み(ドラマでよく見る、あの頃は大変だったなあというやつ)を出すために、過酷な状況に身を置き、何かにチャレンジしてみたいという謎の好奇心に駆られ2年半で退職しました。

ほぼ無計画で退職後、本気を出せば勝てると信じてYouTubeを始め、1年で7万人ほどのチャンネル登録者数を獲得しました。
しかし、諸事情で効率化大好きなエンジニアがプレックスに入社した理由 のみの活動が難しくなり、再就職を決意し今に至ります。

約1年半で社会復帰したため、深みが出たかと言われると微妙ですが、ボロ家で貧乏飯を喰らいながら必死に作業し続けた経験は、大きな財産になると思っています。
いやあ、あの頃は大変だったなぁ...(伏線回収)

プレックスへの入社理由

就職活動中に感じたプレックスの魅力は以下の通りです。

  1. モダンな技術スタック
  2. テックブログから感じたエンジニアの質の高さ
  3. コーポレートエンジニアという役職

募集要項やテックブログを拝見し、エンジニア組織の質の高さや、雰囲気の良さを感じました。 しかし、一番の志望理由はコーポレートエンジアという役職です。

私は物事を効率化させることが大好きです。
個人で沢山のツールやWebアプリを作りましたが、大半のものは効率化を目的とするためのものでした。

  • 就活中に「モチベーショングラフを作って自己分析した方が良い」と人事の方に言われた際に、紙に書くのが嫌すぎてWebで作成できるアプリを作った.
  • YouTube用の動画作成時に字幕をつけるのが面倒だったので自動生成&配置ツールを作った.
  • 新海誠監督が感情曲線を用いて脚本を書いていると知り、感情曲線グラフをプロットしながら脚本を書けるVSCode拡張を作った.

他にも様々なものを作ってきましたが、効率化を目的とした開発が一番モチベーションを持って取り組めるんだと感じていました。

そして、プレックスにおけるコーポレートチームは 「オペレーションの効率化によって事業成長に貢献する」 をミッションとしており、私にピッタリのチームなのです!

入社して半年弱経過しましたが、期待していた以上に自分の価値を発揮できる職種だと感じています。

コーポレートチームについて更に知りたい方へ product.plex.co.jp

入社後に感じたプレックスの魅力

ビジネスサイドとの連携が刺激的

コーポレートエンジニアはビジネスサイドと連携をすることが多いです。業務プロセスの自動化や効率化を行うツールやアプリケーションの作成を通して、会社へ貢献していることを体感できます。

  • LP の開発、Kintoneとの連携
  • 手動で行われていたタスクを Cloud Functions, Cloud Scheduler で自動化
  • etc...

依頼通りに実装するだけでなく、問題の根本的な原因を調査して、より良い方法で解決できた時は、エンジニア冥利に尽きる瞬間です。

さらに、エンジニアとしてだけでは得られない知識や考え方、ビジネスについて触れることができる点も魅力的です。これにより、視野が広がり、新たな発見や学びが日々あります。

なにより、ビジネスサイドとの連携は非常に刺激的です。新しいアイデアやプロジェクトに取り組む際の熱意や創造力は、日々の仕事に大きなモチベーションをもたらしてくれます。

会社の成長を肌で感じることができる

10月のカジュアル面談時には社員数が約150人でしたが、1月の入社時には200人近くまで増え、現在では300人を超えています。

急速な成長を肌で感じることができる環境で、自分の貢献が会社の成長に直結していることを実感しながら働くことができるのは、大きなやりがいとなっています。

裁量がとても大きい

会社にとってメリットがある場合、大抵のことは希望すればやらせてもらえます。

  • Kintone カスタマイズ開発環境の刷新(Turborepo や Typescript の導入)
  • 社内チャットツールのコンポーネントライブラリを Material UI にリプレイス(進行中)
  • etc...

改善点を提案し、自ら解決することができるので、社員一人一人が会社をより良い方向に成長させることができる環境であると感じています。

さらに、エンジニア業務以外のタスクにも携わることができる点も魅力です。様々な業務に関与することで、多角的な視点を持つことができるようになり、開発をしているだけでは得られない経験を積むことができます。

私は入社して半年弱ですが、カジュアル面談を担当させてもらっています。
もし、面談の担当になった際にはよろしくお願いします。

最後に

プレックスではエンジニアを募集しております。
上述の通り、プレックスは現在急成長を続けており、その速度は数字だけでなく日々の業務の中で体感できるほどです。
本記事を読み少しでも共感する点があれば、是非ご連絡ください!
この記事では伝えきれなかったプレックスの魅力を語らせていただきたいので、とりあえず私とカジュアル面談しましょう。

dev.plex.co.jp

プレックス、社内勉強会やってます!!

こんにちは、Plex Job 開発チームの池川です。

エンジニアといえば勉強会、ということで今回の記事ではプレックスでこれまで実施した社内勉強会を紹介したいと思います!

社内勉強会とは

プレックスでは週一の頻度で、エンジニア対象の社内勉強会を行なっています。 そこまでカチッとしたものではなく、お昼の時間にランチがてらエンジニアが集まって雑談する延長、みたいな感じで開催しています。 勉強会のテーマは技術に関することなら何でもOKで、下記のような感じでカジュアルに決めています↓

【Slack】勉強会のテーマ決めのスレッド

今回の記事を書くにあたり、過去のSlackや勉強会資料を振り返っていたところ、約2年前から社内勉強会は行われていたようでした。 ここからはこれまでに開催した勉強会について、内容や教材・目的を簡単に紹介していきます! (第1回〜第3回までは私が入社前の話なので伝聞形式でお届けします…)

社内勉強会の紹介

1. DDD勉強会(2021/12~2022/2)

記念すべき勉強会、第1回のテーマは、DDD(Domain-Driven Design)でした。 初学者が多かったこともあり、教材は「ドメイン駆動設計 モデリング/実装ガイド」を使いました。

DDD をテーマとして選んだ理由としては、

  1. 弊社のプロダクト開発において、事業間の連携が存在し、複雑なドメイン知識を必要とするようになったため
  2. 新しいメンバーがジョインしてドメイン知識の共有に課題があったため

の2つがあったようです。

DDD勉強会を通じて得た知見については、別の記事に詳細をまとめていますのでそちらも参照ください。

product.plex.co.jp

2. TypeScript勉強会(2022/3~2022/6)

第2回は「プログラミング TypeScript」を教材に、TypeScript をテーマとしました。

勉強会は、

  1. あらかじめ決めておいた章を読んでおく
  2. 勉強会の冒頭で Google Jambord に重要だと思った点や、質問・業務に取り入れたいところ、などを貼っていく
  3. その後、付箋をグルーピングして各トピックについて話す

といった流れで進めていきました。

勉強会をする前から TypeScript は使用していましたが、体系的に勉強することで、型宣言の切り分けのベストプラクティスやエラー処理などが理解でき、実務に活かすことができました。

勉強会で使用したJambord

3. RSpec勉強会(2022/7~2022/10)

第3回のテーマは RSpec でした。 弊社ではバックエンドに Rails を採用していることが多いので、教材は「Everyday Rails - RSpecによるRailsテスト入門」を使いました。 この勉強会では本を輪読するだけでなく、より実践的な勉強を行うために下記の手順で勉強会を行いました。

  1. GitHubに専用のリポジトリを作成
  2. 参加者はあらかじめ、対象の章のテストを書いておいてプルリクを出しておく(下記画像参照)
  3. 勉強会では誰かのプルリクを見ながら議論を行う

レビュー形式で勉強会を進めることでより理解が深まったと思います!

勉強会で使用したプルリクのコメント

4. SRE本の輪読会(2023/3~2023/7)

第4回のテーマは、SRE(Site Reliability Engineering)でした。 教材はSRE本「Site Reliability Engineering」で、初めて英語の本を教材としました。(英語だと無料で読めます) 当時、Plex Jobのサービスがスケールする中で、プロダクトをいかに安定稼働させるかが重要なテーマになっていたこともあり、SRE をテーマに選びました。

勉強会後には、Plex Job 開発チームで運用しているOKRに「プロダクトの安定稼働」を設定し、「SLO: 99.9% (時間ベース)」をKRとして、スロークエリの改善や障害発生時に気付ける仕組みづくりなどの改善を行いました。 また、2024年1月にはその延長で Heroku から GCP へのインフラ移行も移行し、一定の効果を実感しています。

product.plex.co.jp

5. 単体テストの考え方/使い方」の輪読会(2023/10~2024/2)

第5回のテーマは単体テストで当時、話題となっていた「単体テストの考え方/使い方」を教材に選びました。

勉強会は

  1. 各章ごとに担当者を決めて、Notion に内容をまとめる
  2. 担当者は事前にまとめたページを共有して、参加者は気になる点や疑問点があればコメントする
  3. 勉強会ではまとめた内容を説明しつつ、適宜、質疑応答を行う

下記のような流れで行いました。

この頃にはPlex Job以外にもSaasやコーポレート、マーケといった事業部ができていたので、各事業部のプロダクトでどのような運用をしているかなど、意見交換できたのも良かったです!

Notionにまとめた勉強会資料

6. 「ソフトウェアアーキテクチャの基礎 ―エンジニアリングに基づく体系的アプローチ」の輪読会(2024/2~実施中)

第6回のテーマはアーキテクチャで、現在もこのテーマで勉強会を行なっています。 教材は「ソフトウェアアーキテクチャの基礎 ―エンジニアリングに基づく体系的アプローチ」を使っています。 直近だと10章のレイヤードアーキテクチャについて勉強会を行いました。

以上がこれまでプレックスで行なってきた勉強会です。

勉強会あれこれ

せっかくなので勉強会を定期的に開催するにあたり、気をつけていることや今後やっていきたいことも簡単に共有したいと思います!

発表者は持ち回りにする

発表者は毎回持ち回りの交代制にしており、特定の人に負荷がかからないようにしています。 現状だと、2,3ヶ月に一回、発表者の役割が回ってくるペースです。

有志が集まって開催する

勉強会は強制ではなく、参加したい人・できる人が集まって開催しています。 また、メンバーによってはリモートワークしている人もいるので、オフライン+オンラインで勉強会を行なっています。

ワークショップの様子

輪読会では必ずしも一冊全てを行わない

教材とした本の内容について全てを勉強会で取り上げるのではなく、業務に関連する箇所や興味のある箇所に絞って取り上げています。 勉強会は大体2,3ヶ月のスパンで扱うテーマを入れ替えており、これくらいの期間で行なっていくのがモチベーションを維持して継続的に勉強会を開催する意味でも良いのではと感じています。

今後やっていきたいこと

ここ数回は輪読会が続いているので、LT会など別の勉強会の形式も取り入れていきたいです。 また、ほとんどの時間を発表者が一人で話して終わり、といった形になってしまったこともあったので、事前に質問を集めたりプロダクトのコードを題材にするなど、発表者以外のメンバーも積極的に勉強会に参加できる仕組みづくりも行なっていきたいと考えています。

さいごに

プレックスでは今回の記事で紹介した社内勉強会の他にも下記のような勉強会やイベントを開催しています。

コンテンツ 概要
社外勉強会 LT会*1
株式会社プレックス 社内ISUCON ISUCON*2 の社内版
開発本部定例 隔週で開催、業務で得たTipsなどを持ち回りで共有

※1 LT会の詳細はこちらの記事を参照ください

※2「ISUCON」は、LINEヤフー株式会社の商標または登録商標です

また、今年初の社外オフライン勉強会として2024年6月にLT会を開催する予定です! 詳細が決まり次第、connpass でイベントを公開しますので、興味がある方はぜひ参加いただけると嬉しいです。

plex.connpass.com

最後に、弊社では全ての事業部でエンジニア採用を積極的に行なっています。少しでも興味を持っていただけた方は業務委託や副業からでも、ぜひご応募ください!

dev.plex.co.jp

【入社エントリ】 プレックスに入社しました!

はじめに

初めまして、エンジニアの石川と申します。

2023年9月に株式会社プレックス(以下、プレックス)に中途入社いたしました。

入社して半年以上経ち、入社エントリーを投稿するには少し遅れてしまいましたが、半年以上経った上で見えてきた、会社の良さや日々の業務内容をお伝えできたらと思います。

簡単な自己紹介

簡単に私の経歴をお伝えすると、プログラミングスクール黎明期に仮想通貨で獲得したお金を元にプログラミングスクールに通い、そこから渋谷のベンチャー企業にて毎日プログラムを書きながら、時には1年放浪し紆余曲折ありながら今に至ります。

2018年 短期集中プログラミングスクール TECH::EXPERT(株式会社div) 入学
2019年 ~ 2022年4月 株式会社テモナ入社
2022年4月 ~ 2022年10月 株式会社speee入社
2022年10月~2023年9月 放浪
2023年9月~ 株式会社プレックス入社

小学4年生からPCのFPSなどはやっていたものの、プログラミング自体は社会人になる直前にスクールで学習したぐらいでしたので、かれこれ4年もプログラミングをしている自分にびっくりしてます。

プレックスへの入社理由

人として良いエンジニアが多いと感じたのが一番です。

僕自身「価値のあるサービスを作る」「保守性の高いソースコードを書き続けたい」などの思いももちろんありますが、休みの日も楽しくソースコードを毎週かけるかと言われたら、ゲームを友達とやる方がおそらく楽しいと内心は思ってます。

ですが、働く上でエンジニアのメンバー達と技術の話をしたり、良いサービスを作ろうと団結する一種の文化祭みたいな雰囲気はとても好きなので、一緒に働くエンジニアの方々を一番重視しておりました。

また、サービスを作るにあたっても一緒に働きたいと思える人たちと作れなければ、良いサービスを生むことは難しいと思っています。1人でできることには人間限界が絶対にあるので。

エンジニアとしてこのような考えが正しいかどうかはわかりませんが、僕自身はプレックスに入社して大変よかったなと半年間を通して改めて実感しております。

所属しているコーポレートチームについて

入社して現在に至り、コーポレートチームにてエンジニアをしております。コーポレートチームは2023年9月に誕生し、主な業務は下記になります。

  • 社内で利用されているkintoneのプラグイン開発
  • 営業の方の業務改善のためのGAS作成
  • 社内システムの0からの開発
  • 社内データをまとめ意思決定・施策を考えるためのDWH・BigQuery開発・運用

私自身がコーポレートチーム1人目の正社員エンジニアで、CTOの石塚さんと2人で開発を行っておりました。今では正社員のメンバーが2人増え、計4人のチームで日々開発・保守しております!!

コーポレートチームについて更に知りたい方へ product.plex.co.jp

入社してからの感想

課題解決のためのプログラミング

私自身Ruby on Railsでの開発経験が多く、自分の技術スタックベースで課題解決を考えていましたが、「この課題を解決するためにはPythonのライブラリを利用した方がいいよね」のような会話が日常的にあります。

Python未経験でしたがキャッチアップしながらソースコードを書き課題を解決し、改めて課題を解決するために技術があることを感じました。

当たり前と言えば当たり前ですが、自分が触れてきた技術ベースで考えてしまう癖は、気付かぬうちに自分の可能性を狭めているんだなと業務を通して感じられて大変よかったです。

非エンジニアの方の技術に対する理解度が高い

コーポレートチームで働くと、営業・マーケティングなどエンジニア以外の方とコミュニケーションを取ることが多いのです。

その際、「〇〇のデータが欲しいからSQLを△△の条件で書いて」のような依頼ではなく、「SQL書いたんだけど、JOIN周り非効率的で処理が遅いんだよね」のようなSQLなど書いたことなくても、自分で一旦挑戦した上で質問を頂くことがとても多いです。

このような「一旦挑戦してみて無理だったら質問してみる」のスタンスの方が多くて大変驚きました。

改めて前向きなエンジニアが多い

こちらは入社理由でもお話しいたしましたが、良い意味でギャップがなく前向きなエンジニアが多いです。

自分のメイン業務があるにも関わらず、Slackにて技術的疑問や悩みを書き込めば、部署問わずみなさんコメントを書き込んでくれますし、サービスをよくするために自分の開発力を毎日磨いてる方がいたり、自分から提案して開発環境を整備する方もいます。

タスクがあるから仕方なく仕事をするのではなく、自分から能動的に働きかける人が多く、自分ももっと能動的に動けるようになりたいと日々感じております。

最後に

私自身、かれこれ4年ほどプログラミングを行っていますが、漠然とバックエンドが好きなのかなと思う程度です。

先人の強いエンジニアの方と比べて自分の専門領域は何なのか日々向かい合っていますが、こういう方にこそコーポレートチームは合っているのかなと思います。

考えているだけだと悩みますが、一緒に手を動かしながら色々な業務を通じて切磋琢磨できるメンバーを募集しております。

もしこの記事を読んで、興味を持って頂けましたら、是非ともご連絡頂けるとうれしいです!!

dev.plex.co.jp

Plex JobのバックエンドをHerokuからGCPに移行しました

はじめに

こんにちは、Plex Job開発チームの種井です。

先日公開された、池川さんのブログ「HerokuからGCPへのインフラ移行 〜ダブルライト検証編〜 - PLEX Product Team Blog」でも紹介がありましたが、Plex Jobでは昨年から今年の1月まで約8ヶ月ほどかけてバックエンドのシステムをHerokuからGCP(Google Cloud Platform)に移行しました。 順番は前後しますが、今回は移行に至った経緯や完了するまでの取り組みについて、ざっくりと全体像について、お話しできればと思っております。

インフラ移行に至った経緯

弊社では

  • 使われるかどうかわからない段階での作り込みを避ける
  • 限られた人数でまずはアプリケーションの開発に注力するため

MVP段階のプロダクトに関してはHerokuを使用して運用を行うという方針があります。

Plex Jobはありがたいことに求職者様や企業の採用担当者様をはじめ、社内外の多くの利用者様にお使いいただけるところまで成長しました。 それに伴い、よりバックエンドシステムとしての可用性や堅牢性が求められるフェーズに差し掛かっていること、また以下のような直近の技術的な課題の解消も兼ねてバックエンドシステムをHerokuから移行する運びとなりました。

  • Herokuのリクエスト時間制限
  • バックエンドが物理的に遠い

Herokuのリクエスト時間制限

Herokuにはリクエストの処理を完了するまでにかかる時間が30秒以上かかるとHerokuルーターにより強制的にリクエストが切断される制限が設けられています。 このまま放置すると、Web Dynoはそのまま処理を継続しますが、レスポンスはクライアントに返却されることはないため、アプリケーションサーバー側でタイムアウトさせて処理を中断させることになります。(Plex Jobでは25秒に設定していました)

25秒以上かかるHTTPリクエストにそもそもの問題はありますが、とある要件からどうしても大量のレコードに対して複雑な条件で検索をかける必要のある機能があり、設計やクエリの見直しを行いつつも一旦はタイムアウトまでの時間に余裕を持たせたいという事情がありました。

devcenter.heroku.com

バックエンドが物理的に遠い

HerokuのCommon Runtimeでは、DynoやHeroku PostgreSQLインスタンスを建てられるリージョンはUSもしくはEUに限られます。 利用者や開発者は基本的に日本国内のユーザーを想定しているため

  • ページを表示するまでに必要なデータの取得に時間がかかる(読み込みがもっさりする)
  • 開発者が運用業務で行うデータパッチや集計などに時間がかかる

など、クライアントとデータソースの距離がリージョンをまたいで、物理的に離れていることによるネットワーク起因の課題がありました。 また、ユーザー環境に対してサーバーレスポンスが早くなることで、SEO対策上重要となるサイトの表示パフォーマンスの改善も見込んでいました。

移行までにやったこと

移行までに取り組んだことを簡単にまとめておこうかと思います。 大まかには以下となります。

  • 移行計画と移行先の検討
  • IaC(Infrastructure as code)によるGCP上へのインフラ構築
  • アプリケーションの負債の返却と無停止移行に向けた検証
  • 移行作業に向けた準備

移行計画と移行先の検討

まず最初に移行計画を引きました。 SREとして顧問をしてくれているメンバーが現状の構成と課題に基づいて、移行対象と移行までにすべきことを洗い出してくれました。 移行先の選定を含め、移行にあたってどこから何を決めるべきかが明確になりましたし、途中検証を重ねて計画を変更することになった場合でも想定される作業の見通しを立てることができ、プロジェクト進行中の指針となりました。

移行先のプラットフォーム選定

移行先のプラットフォーム選定に関しては、Plex Jobだけでなく今後全社的に使用を推奨するものとして検討を行いました。 AWSやHeroku Private Spaceなどが選択肢として上がりましたが、元々社内のいくつかのシステムがGCPで運用されていること、また複数のサービスでFirebaseやBigQueryなどをすでに使用していることもあったため、社内で技術スタックを統一する意味合いからGCPを選択することにしました。

なぜGKE Autopilotなのか?

GCPで提供されている各サービスを比較検討を行った上で、移行先のプラットフォームやサービスを決めました。

前提として、移行元であるHeroku環境ではアプリケーションのランタイムはContainer Stackで運用されていたこともあり、あえてVMではなく、Cloud RunやGKE(Google Kubernetes Engine)をはじめとしたサービスを使用するところから検討をはじめました。

その中でも

  • 運用コスト
    • GKE: 社内にk8s(Kubernetes)のクラスタ運用に関する知見がない状態でNodeの管理を行うことは極力避けたい
  • Datadogとの互換性
    • Cloud Run: 計画当時はまだ正式版が公開されていませんでした
  • Terraformとの責務分離
    • Cloud Run: Cronや非同期タスクを実行するためにGCPのSchedulerやTasksのようなサービスを組み合わせて使用する必要があるため構成の管理が分散してしまう
      • k8sの場合、エコシステムにのっかりることで、k8sの構成ファイルで一元管理することができます。開発者がTerraformやGCPのリソースを極力触る必要がなく、なるべくコンテクストスイッチも少なくて済むと考えました。

のような観点から最終的に上記の折衷案として、GKE Autopilotを使用することに決めました。 学習コストが高いとされるk8sですが、Autopilotである分、レクチャーを受けつつ自分たちで段階的にものにしていけるのではないか、やっていくぞというCTO石塚と私の強い意気込みもありました。

IaCによるGCPへのインフラ構築

今回の移行にあたっては、Terraformを使用したIaCの実践と今後プロジェクトが増えることを見越した権限管理の整備も目標としていました。 SREとして顧問をしてくれているメンバーにTerraformによるGCP上へのインフラ構築や権限管理をまるっと実施いただきました。 社内にIaSの実務経験のあるメンバーが不在であることから、Terraform講座を開いていただきつつPR(プルリクエスト)をベースに石塚や私も最低限運用上の構成管理ができるようにインプットを並行して行いました。 現在どのようにIaCによってインフラの構成が管理されているかについては、また別途ブログ記事として紹介したいと思います。

また、並行してk8sに関してもハンズオン形式での講座を開いて頂いたり、参考資料を元に自分達でインプットを行い運用に向けて準備を進めました。

移行に向けた検証と環境変数の整理

移行作業を進める中で、アプリケーションが参照している環境変数が多いことが課題に上がりました。というのも、定数管理で済むような値に関しても無秩序に環境変数として登録されているような状態でした。 今回の移行によってこれまで通りGUIから環境変数を気軽に登録できることはできなくなります。 よりインフラのレイヤーで管理すべきものと、アプリケーションのレイヤーで管理すべきものを分離する必要がありました。 そのため、これまで環境変数として設定されたもののうち、アプリケーション側で管理するもの、インフラ側で管理するものを分類し、アプリケーション側で管理するものに関しては、RailsのCredentials機能やSettings Gemに管理を寄せることにしました。 こちらに関しても記事1つ書ける内容なので、詳細はまた別の機会に紹介したいと思います。

また、移行の計画段階では

  1. 定期バッチの移行
  2. APIおよびWorkerの移行
  3. DBの移行
  4. 新旧DBへのダブルライト期間
  5. 旧DBの切り離し

を想定していましたが、検証によりOff SiteなDB接続のボトルネックが予想以上に大きいことがわかったので、途中で無停止での段階的移行を中止し、メンテナンスを入れる前提で、全てのバックエンドシステムを一度に移行する方法に切り替えることにしました。 これに至るまでの検証に関しては、実施内容が池川さんの記事に詳細が書かれているため、参照いただければと思います。

product.plex.co.jp

移行作業に向けた準備と実施

  • 受け入れテストの仕様書作成
  • 新ステージング環境でのQA
  • メンテナンス機能の作成
  • 移行手順書の作成
  • 移行作業のスケジューリング
  • 当日の実施

を行いました。 特に、ステージング環境でのQAを行う前の段階で、受け入れテストの仕様書を作成して本番環境を想定してテストを実施したことにより、項目のブラッシュアップや当日手順の実施がスムーズになりよかったと感じています。 また、メンテナンス機能については、VercelのEdge Configを活用することで比較的簡単に用意することができたので、こちらも別の機会で紹介できればと思います。

vercel.com

リリース後、トラフィックの多い時間帯に一部のPodがリソース不足で動作が不安定になるといった問題はあったものの、特に大きな問題もなく新しい環境で運用を開始することができました。

移行後、運用が開発チームに浸透するまでに実施した内容についても別途運用編としてご紹介できればと思います。

移行を終えて

移行を終えて以下のような構成となりました。

簡略版構成図

移行の経緯に上げた課題についてですが

  • 可用性や堅牢性の向上
    • 求人サイトの突発的なリクエスト増加にも停止時間が発生することがなくなるなど可用性の向上が見られた
    • 以前と比較してセキュリティ上の細かい要件に対応することができるようになった
  • Herokuのリクエスト時間制限
    • リクエスト時間の緩和を行うことができた
  • バックエンドが物理的に遠い
    • データパッチや集計にかかる時間が削減できた

などの効果を実感することができています。

また、現在はインフラにかかるコストの最適化や監視、可観測性の担保です。 コスト最適化の文脈でアプリケーションのパフォーマンス・チューニングにも積極的に取り組んでいきたいと考えております。

おわりに

今回、Plex Jobのインフラ移行についてざっくりではありますが、全体像をお話させていただきました。 記事中でもいくつか紹介しましたが、取り組んだ一つ一つの内容はそれぞれ1つの記事として公開できそうなものも多いため、関連記事として連載していきたいと思います。

Plex Jobだけでもコスト最適化、監視、可観測性などをはじめとした課題がありつつ、他事業部のプロダクトもGCPへのインフラ移行を控えていたりします。 このような課題にチャレンジしていただけるSREをはじめ、ソフトウェアエンジニアフロントエンドエンジニアを募集しています。

dev.plex.co.jp

少しでも興味を持っていただけた方は業務委託や副業からでも、ぜひご応募いただけると幸いです。

大学院を辞退し、初の新卒エンジニアとしてプレックスに入社した理由

はじめに

2024年4月に株式会社プレックスにエンジニアとして新卒入社した佐藤祐飛と申します。プレックスでは初の新卒エンジニアとなります。現在は、SaaS事業部にてサクミルという建設業界向けのプロダクト開発を行っています。

sakumiru.jp

タイトルにもある通り、私は学部4年生の夏頃までは大学院へ進学予定でしたが、インターンを通してプレックスでのファーストキャリアを歩みたいと考えるようになりました。

そんな私の体験談を共有しながら、読者の皆様にプレックスについて知ってもらいたいと思い、この記事を書きます。

学生時代について✏️

横浜国立大学情報工学EPを卒業しました。学生時代は学業に力を入れており、学科内で首席になった学期もありました。

首席の表彰状

海外で働いてみたいという夢があり、オンライン英会話やTOEICなどの英語学習にも力を入れていました。日々の学習の甲斐あって学部3年生の春頃にTOEIC915点を獲得することができました。

弊学科は約9割の学生が大学院へと進学するので、私も当然のように学部1年生の頃から大学院進学をする予定でした。

プレックスとの出会い🌸

学部4年生になるまで、私は開発経験が全くなく、授業でC言語Javaを触った程度でした。春頃に配属先の研究室で行われた就活座談会にて、WEB系のエンジニア就活ではインターン経験がないと話にならないということを知り、インターンを探すことになります。インターン募集に手当たり次第応募し、面接をしていく中でプレックスと出会いました。今思うと、ここが人生の分岐点だったなと感じます。

初めてテックリードと面談した際には、 「君は僕を超えるエンジニアになるかもしれない」や当時、インフラエンジニアを志望していた私に対して「君がインフラエンジニアだけで可能性を閉じてしまうのは勿体無い」など有り余るような評価をしていただきました。

その後、インターン選考としてRuby on RailsとNext.jsを利用した企業データ管理アプリケーションを作成する技術課題が出題されました。WEBアプリケーションを1から作るのは初めてでしたが、テックリードと仕様検討をしながら課題を進めるという形式だったので楽しく取り組むことができました。

他にもインターンの合格をいただいていましたが、開発未経験であるにも関わらず自分が評価されていることや、フルスタックの開発を通じて自分の可能性を広げてみたいという理由からプレックスでのインターンを決めました。インターン採用方針などについては、テックリードの記事に詳しく記載されています。

product.plex.co.jp

プレックスでのインターン🌊

インターンは学部4年生の8月から開始しました。この時点では既に横浜国立大学大学院の合格をいただいており、大学院を蹴ることになるとは夢にも思っていませんでした。

印象的なタスクについて

最初に任されたタスクはAPIからリソースをフェッチしている間のローディング画面にスケルトンを表示させるというものでした。ドキュメントを読みながら実装して、プルリクを出しました。その後のレビューにて私が書いたコードは丸っと修正されており、細部までこだわったスケルトンが実装されていました。その際に、「プロ意識が足りていない」というフィードバックをいただきました。求められている水準を再認識し、タスクに対して真摯に思考する能力が必要だと強く実感しました。

インターンを始めて2ヶ月目には、サクミルの社内管理画面を作成するタスクを担当しました。当時はサクミルを利用するユーザーのアカウントを発行する際に、ビジネスサイドの方が認証基盤にユーザー情報を登録し、サクミルのDBにそのユーザー情報を登録、最後にアカウント発行のメールを送信するという3ステップを手作業で行っていました。これを管理画面上で一度に行いたいという要望がありました。エンジニアになって2ヶ月目にも関わらず大きな裁量をいただき、PdMと仕様を検討しながら開発を進めました。管理画面が完成し、初めて利用していただいた際には、サクミルチームが湧いたことをよく覚えています。このタスクを通じてビジネスサイドと距離が近い環境で開発を行いたいと考えるようになりました。

きっかけはPdMの一言⚡️

学部4年生の10月に私が「SaaSの立ち上げ期に携われるのは楽しいけど、エンジニアなら大規模サービスにも関わってみたいですよね」という話をPdMにしたところ、PdMから 「1つのサービスの立ち上げから、大規模になるまで自分でやっちゃえばいいんだよ」 という一言をいただきました。あ、そっか。自分でやればいいんだと思いましたね笑。単純ですが、個人的にはコペルニクス的転回でした。

この時点まで、私は大学院進学をするつもりでしたが、この一言がきっかけで学部卒でプレックスに就職した方がよくないか?という疑問が湧いたのです。もちろん、大学院に進学しそのままサクミルでのインターンを続けるという選択肢もありましたが、正社員という当事者として急激な成長期のサクミルに携わる経験が長期目線で自身の成長につながると考えました。そして、学部4年生の2月に内定を承諾しました。

プレックスに入社した理由🔥

プレックスに入社した理由をもう少し分割したいと思います。

豊富な打席に立ち続けることができる

前述した通り、サクミルは急激な成長期にあるため、エンジニアには様々な打席(タスク)があります。そのため、たとえ新卒1年目であっても、難しい打席で裁量を持ってバットを振ることができます。

これは技術力が高いとされる企業と比較した際のメリットであると考えています。プレックスでは常に自分の能力値ギリギリの打席に立つ事ができるので、他社と比較してより成長できる環境だと考えました。

面白い打席については随時、開発者ブログに投稿していきます。

優秀なメンバーと事業を成長させることができる

プレックスには、優秀なメンバーが数多く在籍しており、メンバー1人1人が事業成長に対して熱量を持っています。業務時間中にプロダクトに関して熱く議論を交わすのは日常茶飯事です。議論のレベルが高いので、私はついていくのでやっとです汗。

また、サクミルが対象とする建設業界の国内における市場規模は経済センサス‐活動調査(METI/経済産業省)によると 約112兆円で超巨大です。さらに、建設業界はレガシー業界でIT化がそれほど進んでいない業界でもあります。そのため、発足1年程度のサクミルにはとても大きな伸び代があります。

私は、優秀なメンバーとこんなにも大きな挑戦ができることにワクワクを抑えきれませんでした。そのため、仮に大学院へ進学しても研究を放り投げてプレックスのインターンに時間を投下することは目に見えていたので、それならいっそ入社してしまったほうが良いと思いました。

最後に

プレックスではエンジニアを募集しております。特に我こそは新卒2人目のエンジニアになりたいという方は是非連絡をください! dev.plex.co.jp

最後になりますが、入社するにあたり、プレックス関係者や研究室の先輩・OBの方々に何度も相談に乗っていただきました。皆様のおかげで迷いのない意思決定をすることができました。本当にありがとうございました。

プレックス初の新卒エンジニアの名に恥じないように日々精進して参りたいと思います!

立ち上げ期のSaaS事業におけるエンジニアインターンの採用について

SaaS事業 テックリードの石見です。

2023年4月からSaaS事業を立ち上げており、エンジニアインターンを採用しました。
結論、最高の結果になったため、誰かの助けになればと思い詳細に記載することにしました。

SaaS事業の立ち上げの変遷は前回の記事をご覧ください。 product.plex.co.jp

前提

当時の状況を記載します。

4月から立ち上げを行い、事業が急成長していました。
6月には新規開発、既存機能の改善、事業における技術的な意思決定を1人で進めていくのが物量として限界でした。

コード品質と仕組み化には、こだわっていたため育成環境はありましたが、事業はまだまだ不確実な状況でした。

正社員の採用活動と同時にインターンの採用活動も行うことにしました。

採用要件

要件は以下のようにしました。

必須項目

プログラムによる実装経験がある

if, for とはなんですか?からの育成はコストが大きすぎるため。

※就業・実務の経験は問わない。

週3日以上の出社(研修期間中)

初心者は「何がわからないかわからない」ので、テキストコミュニケーションが困難であるため。

また「社員の時間を奪いたくない」「できないと思われたくない」などの質問への萎縮も発生しやすいので、様子を見てメンターから声をかけたいため。

そして、ドメイン知識のキャッチアップのため。

推奨項目

事業で結果を出すことに興味関心・意識が向いている

立ち上げ期は、意思決定の前提となる条件が大きく変わることが多いです。

また、事業責任者・顧客・競合でさえも正解がわからないことも多いです。チームのひとりひとりが自身の専門性と価値観から意見をぶつけることが重要です。

技術としての成功、タスクとしての達成を超えて、事業に意識が向いていることを推奨としました。

採用フロー

募集

伝えたこと

企画、設計、実装のすべてのプロセスに関われること

立ち上げ期であり、やるべきことは大量にあります。

企画、設計、実装から、それがどう事業に影響を与えるかのすべてのプロセスに関われることが強みとなります。

成長プロセスの明記

立ち上げ期は不確実性が高いため、不安に感じる場合もあります。そのため、プロセスを明記しました。

以下のスプリントを1~2週間で1周します。

・課題と企画と仕様の把握
 ・課題に対して、企画が妥当であるか。企画に対して仕様が妥当であるかを整理します。
・設計
 ・整理した仕様を元に設計を行います。シンプルで良い設計になるまで議論します。
・実装
 ・設計通りに実装をします。シンプルな実装になるようにレビューします。
・振り返り
 ・開発が終わるごとに、学んだこと、疑問だったことなど、成長を言語化して共有します。

学生のキャリアに貢献すること

学生の時間は本当に貴重です。その時間をいただくからには責任を持ってキャリアに貢献することを明記しました。

選考

前提

最初に事業立ち上げにおいて、優秀なエンジニアを定義しました。

  • 技術力が事業の決定打になることは、ほぼない。
    • 当たり前の機能の検証が多いため、大抵は入力 -> 保存 -> 表示で十分である。
  • 性能の最適化が事業の決定打になることは、ほぼない。
    • パソコン、スマホなどデバイスの性能が上がった時代。
    • 事業がスケールしない限りは、最適化が必要な状況はほぼ起こらない。
  • 言語、フレームワークの経験値が事業の決定打になることは、ほぼない。
    • 1週間あれば入門して、アウトプットを出せる時代。
    • 当たり前の機能の検証が多いため、大抵は入力 -> 保存 -> 表示で十分である。
  • Copilot・ChatGPTの登場した現代。
    • 正しい指示ができれば8割の精度で自動生成できる。

→ 課題を特定できて、解決策を提示できて、それを仕様や設計に落とし込めるエンジニアが優秀となる。逆にこれらができれば実装はシンプルになり、自動生成も可能となる。

※もちろん技術のプロとして技術力は非常に重要です。ただ、立ち上げ期は技術力以外の比重が大きくなると考えています。

1. 面接

大きく3点を確認しました。

気持ち

  • なぜ応募したのか
    • 直近の将来像、求めているもの
  • なぜエンジニアなのか
    • 長期的な将来像、欲望、野望

行動

  • (気持ちの回答に対して)そのために何をやったか、やっているか
    • 具体的な行動内容と意図
  • 上手くいったこと、上手くいかなかったこと、その理由
    • 課題と要因
    • 自責と他責の認識
  • アウトプット
    • インプットだけでなく、アウトプットしているか
  • 毎日3時間以上技術に触れているか、触れることを習慣にできるか
    • 量を積めるか、失敗をできるか

対話

  • 抽象的な表現が出てきた際に質問する
    • 具体と抽象の思考と、その場で定義ができるか
  • トレードオフな質問をする
    • 状況と情報の整理と、意思決定ができるか

2. 技術課題

アウトプットを出していただければ、フィードバックをして育成はできると考えたため、今の本人の最大限をアウトプットする能力を確認できる内容にしました。

また、Copilot・ChatGPTでは回答が難しく、事業で結果を出すことに興味関心・意識が向いているかを確認できる内容にしました。

結果として「シナリオとヒントを伝えて自由にシステムを実装をしてもらう」という非常に抽象的な課題となりました。

シナリオ

ダミー社は、企業の経営情報を元にシステムの営業をする会社です。

今までは、スプレッドシートやエクセルやテキストなど、部署や個人で管理していた企業情報ですが、DXの流れもあり、社内の企業情報を1つにまとめた検索システムを構築することになりました。

あなたは、現状と課題を整理して、仕様と企画を定め、素敵なシステムの実装と運用をする必要があります。

レギュレーション

  • Rails + Next.jsで実装してください。
  • 質問は3回までOKです。
    • 複数の質問を1度に送ったら1回としてカウントします。
    • 課題の特定、実装方針の決定、成果の確認で利用するのがおすすめです。
  • 2週間以内にGithubで提出してください。
    • 合否にかかわらず必ずフィードバックをします。

3. フィードバック面談

学生の貴重な時間をいただくからには、合否にかかわらず「参加して良かった」と思っていただけるくらいのフィードバックをしたいと考えていました。

評価点

  • 情報整理
    • 課題を捉えているか
    • 質問をしたか
    • 質問の視点がエンジニアを超えて事業へ向かっているか
  • 実装力
    • 実装方法の妥当性
    • 実装内容の妥当性
    • 実装順序の妥当性
  • システム
    • 不具合がないか
    • UI / UX
    • データの正規化
  • その他

Githubを一緒に見ながらフィードバックをしました。 「ここはできている」「ここはもう少し」「この視点があると良い」「こう実装すると良い」と背景と意図を具体的に伝えることを意識しました。

また、学生の貴重な時間をいただくからには、必ずキャリアに貢献したいと考えていたため、インターン期間が中途半端に終わらないようにフィードバックの後に「Nヶ月いただければ成長にコミットできる」と伝えて、インターン期間の合意を得ました。

4. CTO面接

ここまでは私1人で行うため、独断と偏見にならないようにCTO面接を最終面接として行いました。

結果

実務未経験者を対象としたため、2週間という短い期間でしたが非常に多くの応募をいただきました。

  • 応募: 62
  • 書類選考合格: 34
  • 面接合格: 19
  • 技術課題提出: 9
  • 技術課題システム動作: 5
  • 最終合格: 3

最終合格となった3名は、システムの提案資料と技術資料を作ってプレゼンをした方や、「この会社の営業方式はオフラインですか?オンラインですか?」といった非常に具体的な業務プロセスを質問して課題を特定した方や、非常にミニマムな実装のみでシステムを実現した方など、本当に素晴らしい方々でした。

感想

まず、選考に関わってくださった学生の方々、本当にありがとうございました。

若い方から学ぶことは多かったです。

合否に関係なく、学生の夢や思考を聞いて一緒に議論して課題を進めた時間は本当に楽しく眩しかったです。

ほぼ1人で採用活動を行いましたが「事業の成長と学生への貢献」の両立を実現する結果となり、嬉しかったです。

次回は、採用後の育成について執筆をできたらと考えています。

... 最後に

「事業で勝てるエンジニア」「事業と技術の両軸」を志している方は、ぜひ連絡をください。

一緒に闘いましょう。