HerokuからGCPへのインフラ移行 〜ダブルライト検証編〜

アイキャッチ

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

Plex Job では従来、バックエンドのデプロイ先として Heroku を使用していましたが、2024年1月に GCP に移行しました。 移行にあたって、移行後しばらくはいつでも旧環境に切り戻せるようにしておく必要があったほか、切り戻し時に発生するサービスの休止時間もなるべく抑えたかったため、新旧 DB にダブルライトする方法が取れないか検証しました。 結論としてはダブルライトは不採用としたのですが、不採用とした経緯も含め検証して得た知見を今回はまとめたいと思います。

検証環境

設計

ダブルライト実行の大まかな流れは下記です。

  1. 新環境 DB に該当レコードの書き込みを行う
  2. 書き込み結果のレコードを取得する
  3. 非同期タスクのジョブとしてキューを作成する
  4. Worker によりジョブが実行され、旧環境の DB に 2.が書き込まれる

ダブルライトの実行対象は /graphql エンドポイントへの Mutation クエリとしました。 また、新環境への影響を考慮して旧環境 DB への書き込みは非同期タスクとし、非同期タスクのジョブとしてキューを登録するタイミングは ApplicationRecord の after_commitコールバック時としました。 なお、非同期タスクの実行にあたっては Delayed Job を使いました。

設計時に考慮した点がいつくかあったので紹介します。

1. コールバックは順番が保証されているか

同一のトランザクションの各操作に対するコールバックの順番が保証されているかどうか検証しました。 例えば下記のように新規登録したデータを元に別のモデルのデータを更新するケースです。

ActiveRecord.transaction do
  user = User.create!(name: params[:new_user_name]) # ①

  product = Product.find(params[:product_id])
  product.update!(price: params[:new_product_price], updated_by_user_id: user.id) # ②
end

after_commit使用して旧環境 DB への書き込みした際にも ① → ② の順番が正しく担保されるか検証した結果、順番通りに実行されており問題ありませんでした。 ただし、同一のトランザクション内で同じレコードに対して書き込みを行うと、後続のレコード更新時にコールバックが実行されない問題があるため、場合によっては下記の記事で紹介されているような対応が必要となります。

zenn.dev

2. コールバックがスキップされる ActiveRecord のメソッドがある

ActiveRecord のメソッドの中にはコールバックがスキップされる、つまりafter_commitが呼ばれないメソッドがあります。 例えば下記のようなメソッドです。(一覧はこちらにまとめられているので参照ください)

  • insert_all
  • update_all
  • delete_all
  • update_column
  • update_columns

上記のメソッドを使用している箇所はそれぞれ下記の対応を行いました。

  • insert_all などを使用しているところで扱う件数が少ない箇所
    • create, save, update を使って一件ずつ登録・更新するように変更してafter_commitを使用する
  • insert_all などを使ってバルクインサートした方が良い箇所
    • after_commitは使用せず、バルクインサートした後に個別に非同期タスクのキューの登録処理を実装する
  • update_column などを使っていてコールバックを敢えて使用したくない箇所
    • after_commitは使用せず、update_columnした後に個別に非同期タスクのキューの登録処理を実装する

3. Active Storage に対応可能か

Active Storage にファイルを保存する際、active_storage_attachments テーブルと active_storage_blobs テーブルにデータが書き込まれていたため、対応する必要がありました。 それぞれのテーブルの役割は下記を参照ください。

railsguides.jp

upload_file = ActiveStorage::Blob.create_and_upload!(
  # 省略
)

user = User.find(params[:id])
user.file.attach(upload_file)

attachment_attributes = user.file.attachment.attributes # active_storage_attachments テーブルの値
blob_attributes = user.file.blob.attributes # active_storage_blobs テーブルの値

# キュー登録の処理を実装する

ActiveStorage の一連のアップロード処理で作成されるレコードは上記のような形で取得できるため、項目 2 で紹介したバルクインサートのケースと同様に、ファイル登録処理のタイミングで個別にキューを作成するようにしました。

次にどのような実装を行なったかコードを元に説明していきます。

実装

1. 設定の追加

旧環境 DB への接続情報を database.yml に追加します。 今回は replica_db という名前としましたが任意の名前を設定可能です。

development:
  db:
    <<: *default
    url: <%= Settings.db.url %>
  replica_db: # 以下、追加
    <<: *default
    url: <%= Settings.replica_db.url %>

合わせて、Rails 標準で実装されている水平シャーディングを使って、レプリカ DB への接続設定を ApplicationRecord に追加します。 replica_dbの部分はdatabase.ymlで設定した名前と合わせます。

class ApplicationRecord < ActiveRecord::Base
  # 省略

  connects_to shards: {
    default: { writing: :db, reading: :db },
    shard_one: { writing: :replica_db, reading: :replica_db }
  }
end

2. モジュールを作成する

ダブルライト用のモジュールを作成します。

module DoubleWrite
  extend ActiveSupport::Concern

  included do
    after_commit :double_write, if: :on_cloud_sql? # 新環境 DB(cloudSQL)に書き込みされた時のみDoubleWriteが実行されるように設定
  end

  private

    def double_write
      operation = determine_operation
      attributes = previous_changes.transform_values(&:last) # 変更内容を取得

      DoubleWriteJob.perform_later(self.class.name, attributes, operation, id) # 非同期タスクのキューを登録
    end

    def on_cloud_sql?
      ActiveRecord::Base.connection_pool.db_config.name == 'db' # database.yml にある新環境 DBの名前を設定
    end

    def determine_operation
      return 'destroy' if destroyed?

      previous_changes.include?('id') ? 'create' : 'update' # idが含まれていれば更新処理、含まれていなければ新規登録処理
    end
end

新環境 DB に接続した場合のみ after_commit が実行されるようにします。 非同期タスクには今回は下記のような値を渡すようにしました。

名前 内容
self.class.name データの登録・更新があったモデルのクラス名
attributes 登録・更新内容
operation 処理名(create or update or destroy)
id 更新・削除の場合、対象のレコードの ID

3. ApplicationRecord でダブルライト用のモジュールを読み込む

モジュールは各モデルに継承されている ApplicationRecord でインクルードするようにします。

class ApplicationRecord < ActiveRecord::Base
  # 省略

  include DoubleWrite # ダブルライト用のモジュールの読み込み
end

4. ダブルライトを実行するジョブを作成する

非同期に実行するジョブを作成し、旧環境 DB に書き込む処理を書きます。 ActiveRecord::Base.connected_to を使って旧環境 DB にコネクションを切り替えした中で operation(create や update など)に応じた処理を行うようにします。

class DoubleWriteJob < ApplicationJob
  queue_as :double_write

  def perform(model_name, attributes, operation, record_id = nil)
    ActiveRecord::Base.connected_to(shard: :shard_one) do
      model_class = model_name.constantize

      # operation(create or update ...)ごとの処理を実装する
      # 例:create
      ActiveRecord::Base.connection.reset_pk_sequence!(model_class.table_name)
      model_class.create!(attributes)
    end
  end
end

旧環境 DB への書き込み時に注意する点として、新規登録時には ID の自動採番の不整合が生じないように reset_pk_sequence! を使ってデータを登録するようにしました。 reset_pk_sequence!を使えば該当テーブルの最大IDを取得し、次に挿入されるレコードのIDとして設定することができます。

apidock.com

主な実装は以上です。 最後に検証してみた結果をまとめます。

検証してみて

実装後、テストをしたところ画面上で会員登録したり求人に応募したりする分には問題ありませんでしたが、データの一括インポートなど高負荷な書き込み行った際にダブルライトの処理完了までに大幅に時間がかかることが分かりました。 1,000 件程度の一括アップロード処理で、旧環境 DB への書き込みが完了するのに 1 時間程度かかるといった状況です。 旧環境 DB への書き込みに時間がかかってしまうと新環境と旧環境でデータに差分が生じ、当初の目的である障害発生時にスムーズに旧環境に切り戻すことができないため、今回ダブルライトの採用は見送りました。

また、時間がかかってしまった原因ですが、Heroku は us リージョン、 GCP は asia-east1 リージョンにそれぞれデプロイしており、物理的にサーバの距離が離れているため時間がかかったのかと考えています。 なので環境によってはインフラ移行時にダブルライトを採用するのはアリかもしれません。

さいごに

今回の記事ではインフラ移行時に検証したダブルライトについて、約1ヶ月間の検証を通して得た知見をまとめてみました。 ゼロから実装するにはいくつか詰まる点もあったため、何かの参考になれば幸いです。 今回取り上げたHeroku から GCP への移行は Plex Job にとっても一大プロジェクトだったため、インフラ移行に関する記事は後日改めて公開する予定です。

最後になりますが、プレックスではソフトウェアエンジニアフロントエンドエンジニアを絶賛募集中です! 少しでも興味を持っていただけた方は業務委託や副業からでも、ぜひご応募いただけると嬉しいです。

SaaS事業の1人目のエンジニアが1年目にやったこと

2023年4月にSaaS事業の1人目のエンジニアとして入社しました、プレックスの石見です。

SaaS事業の立ち上げにおいて、1人目のエンジニアが1年目に何をやったかをまとめます。

経歴について

DeNA(新卒) -> YOUTRUST -> プレックスとなります。

▼「なぜプレックスに入社したのか?」は、以下の記事をご覧ください。

note.com

SaaS事業について

現場作業が伴う事業者向けの業務効率化SaaS「サクミル」を運営しています。

2022年末からの大幅なピボットを経て、事業化に至ったタイミングで私が1人目のエンジニアとして入社しました。

sakumiru.jp

4月、SaaS事業は「機能がないと始まらない」

  • 入社
  • ドメインのキャッチアップ
  • 既存コードのキャッチアップ
  • 写真台帳機能のリリース
  • ChatGPTとCopilotを福利厚生に追加

入社して最初にドメイン(市場・顧客・競合)について学びました。良い設計、良いソフトウェア、良い実装は、特定の前提条件において「良い」ものになります。ドメイン(市場・顧客・競合)を知らなければ良いエンジニアにはなれないため、特に重視しました。

そして、プロトタイプのサービスがあったため、既存コードのすべてに目を通して理解をしました。現状はすべて過去の「当時の最善」の意思決定によって作られているので「なぜこの技術選定なのか」「なぜこの実装なのか」までを過去の議事録に目を通してキャッチアップしました。

また、写真台帳機能という大きめの新機能をリリースしました。

最後に、ChatGPTとCopilotを福利厚生に加えるように会社に提案をして受け入れていただきました。

5月、3ヶ月後の未来に備える

ピボットの関係で、現状と合っていないデータ構造が見られたため、テーブルスキーマを整理しました。テーブルスキーマが正しければアプリケーションコードはシンプルなものだけで良いため、事業検証の速度と開発の速度が担保できます。そのため、当たり前な機能の開発が主となるSaaS事業の立ち上げでは「テーブルスキーマの正しさ」は特にこだわった方が良いと考えています。

合わせて、アプリケーションコードのリファクタリングも行いました。

そして、事業進捗の速度を考えた時に私1人での限界が予想できたため、インターン生を採用することにしました。「なぜ業務委託でなくてインターン生なのか?」については、立ち上げ期の混沌においてはスタンスが固まり切っていない学生の方が適応力が高くパフォーマンスすると考えたためです。また、シンプルな機能実装でも学生にとっては貴重な機会となるため、学生のキャリアに貢献できるのも良いと考えました。

インターン生を採用するに当たって「なぜ採用するのか?」「どのような学生を採用したいか」「どうやって確かめるか」「何をお互いに合意した上で採用とするか」を決めました。

6月、変化を予期して、起こす

  • インターン生の採用面接
  • インターン生の技術課題のフィードバック
  • パフォーマンスの改善
  • フロントエンドのリニューアル計画
  • カレンダーの実装

インターン生の採用をはじめました。育成前提で経験を問わなかったこともあり、結果として60名ほどの応募が来ました。ほぼ全員と面接を行いました。

事業と技術の両軸に関心がある学生を見極めるために、抽象的な技術課題を設けました。抽象的な課題であることから質問を可能としていたため、質問対応を行いました。技術課題を提出をしていただいた学生には必ずフィードバックをすると決めていたため、提出された技術課題を読み込んでフィードバックを行いました。

また、サービスのパフォーマンスの改善を行いました。

そして、プロトタイプから脱却をするためにフロントエンドのリニューアルの計画をしました。私がフロントエンドの専門性が高いエンジニアではなかったため、フロントエンド周りの技術のキャッチアップを行いました。技術の変遷を理解するのは非常に面白かったです。

最後に、スケジュール機能のためのカレンダーの実装をしました。

60名の方との面接を1人で行ったこともあり、喉を激しく痛めてしまいました。人事の方をより尊敬しました。

7月、「正しさ」を正解にする

  • フロントエンドのリニューアル
  • インターン生の採用決定

フロントエンドのリニューアルを行いました。Next.js 13(App Router)を採用して、アーキテクチャにはBulletproof Reactを採用しました。「事業立ち上げ期で機能の境界が固まり切ってないことから、featuresはroutingごとに切る」などの規約も多く策定してESLintで担保されるようにしました。

github.com

リニューアルやリファクタリングは「本当に必要なの?」と言われることもありますが、自分だけが見えているリスクやコストを整理して、提案と説得をして、結果として「正しさ」を事業の正解にするのがアーキテクトやテックリードの責務だと考えています。

また、インターン生1名の採用を決めました。本当に素敵な学生と出会えて運が良かったです。採用方針や技術課題の内容も非常に良かったことを実感しました。

既存のサービスの開発をしながらリニューアルに向けて、とにかく意思決定をして手を動かしていました。

8月、1人からチームになる

  • フロントエンドのリニューアルのリリース
  • インターン生の受け入れ
  • スプリント開発とチケット管理の仕組みの構築

ついに、フロントエンドのリニューアルをリリースしました。サービスとしても非常に見栄えが良くなりました。開発体験としても適切な切り分けと規約によって意識する箇所が減り、開発速度が大きく向上しました。

そして、インターン生が来てくれました。1人でなくなった喜びもありつつ「未経験の学生をどうやって伸ばしていくか」というマネジメントと向き合いました。開発体験が向上してキャッチアップが容易になっていたこともあり、月末には1人のエンジニアとして活躍していただいていました。

また、1人でなくなったため、スプリント開発とチケット管理の仕組みを構築しました。

9月、プロダクトチームになる

  • スケジュール機能のリリース
  • チケット管理の仕組みを改善
  • ドキュメントの整備

スケジュール機能をリリースしました。少しだけ大変でした。

チケット管理の仕組みにPdMの領域を取り入れました。これによって、要望 -> チケット -> 仕様 -> 進捗 -> PRまでが可視化されるようになりました。可視化されたことで、開発速度が向上しました。

最後にドキュメントの整備を行いました。

個人的には「プレイヤーとマネージャーの切り替え」に苦しみましたが、事業としては「パーツが揃った」と感じました。

10月、開発速度の躍進

フロントエンドのリニューアルから2ヶ月が経過して、一部の機能において想定と異なっていた箇所があったため、リニューアルを行いました。

また、不要な機能の削除を行いました。定期的な引き算は非常に大事だと実感しました。「また必要な時に考えて、再実装する」で良いです。

そして、前提が変わった箇所もあったためテーブルスキーマの整理とアプリケーションコードのリファクタリングを行いました。この際に日本語で表現する概念図とテーブルスキーマを表現するテーブル図を作成しました。これによって、サービス内の概念と表す単語と関係性の共通認識が取れるようになり、議論の質と速度が向上しました。

さらに、インターン生をもう1名採用しました。活発な2名の学生のおかげでチームに活気がつきました。学生から学ばさせていただくことは多いと実感しました。

最後に開発速度の向上によってリリース内容の把握が難しくなったため、リリースフローの整備を行いました。

開発速度が大きく向上しましたが、レビューや実装方針の決定など私がボトルネックになってしまうことが増えました。

11月、「個の最大値」をチームで超える

  • スケジュール機能の追加リリース
  • テーブルスキーマの整理
  • コミットとPRの仕組みの構築
  • ドキュメントの整備

スケジュール機能を拡張して追加リリースしました。こちらはインターン生の主導で開発をしていただきました。非常に良い機能になりました。

テーブルスキーマの整理を行いました。今回は概念の整理ではなくて、項目を増やしたりなど機能の拡張を行いました。

また、コミットとPRの仕組みを構築しました。これによって、レビュー工数が減り、リリースノートが自動で生成されるようになり、リリースフローの管理がより詳細になり、より容易になりました。

最後にドキュメントの整備を行いました。

チームとして最大値が出せるようになりました。

12月、次のステージへ

原価粗利管理機能をリリースしました。繊細な機能でしたが今までの仕組みと開発体験の向上のおかげもあり、楽に実装ができました。今後の複雑な機能も素早く丁寧に開発ができると確信しました。

テーブルスキーマの整理を行いました。今年中にすべてのテーブルの整理を終わらせるのが目標だったため、気合で進めました。

また、独自ドメインからのメール配信の対応を行いました。セキュリティの対応もあり、学ぶことが多かったですが、無事に対応ができました。

最後に、プロトタイプの完全廃止を行いました。

1年目を生き残っての感想

まず、本当に楽しい1年でした。人生の中で1番楽しかった。

個人としては「SaaSは1人でも実装できる。」を実感しましたが、事業の速度に追いつくには「1人では無理だ。」も実感しました。

この「事業に置いてかれないように、自分を拡張できるか。」という恐怖と「自分の理想を実現できるか。」という挑戦と、ずっと闘った1年でした。

そして「今の自分を乗り越える」「市場と顧客に貢献できる」「メンバーのキャリアを広げる」といったことが非常に楽しかったです。

来年はさらなる飛躍を控えているので、引き続き事業と技術に向き合っていきます!

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

折れないで、一緒に闘いましょう。私はまだ闘い続けます。

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

自己紹介

初めまして。コーポレートチームの関(@nori_mashimashi)と申します。 プレックスには2023年11月に中途入社しました。ITエンジニア歴は18年になる昭和世代です。

簡単に経歴を紹介しますと、まず社会人生活の入口は陸上自衛隊でした。東部方面管制気象隊に配属され宇都宮飛行場の航空管制システム、気象情報システムなどのメンテナンスに従事しました。その後、民間のシステム会社に移り、20代の頃はSIerやパッケージベンダでエンタープライズ向けの開発に従事しました。30代になってWebの開発に移り、前職は高速バスの予約サイトコントローラ、前々職は宿泊業向けの予約サイトコントローラの開発に従事していました。

ただ、コロナで観光・宿泊業が大きな影響を受けたのを機に、特定の業界向けのシステム開発ではなく、汎用的に使える技術・知識を身に付けようと思いコーポレートエンジニアに転職しました。

プレックスへの入社理由

私がプレックスを選んだのは次の理由からです。

  • インフラ産業を支え「日本を動かす仕組みを作る」という企業理念への共感
  • 発足したばかりのコーポレートチームのチームビルディングに関われる
  • 急成長中の会社でありコーポレートエンジニアの仕事が山積みである

プレックスはほぼ毎週のように新しい社員が入社して、爆発的に成長しています。その会社をテクニカル面で支えるコーポレートエンジニアに挑戦しがいを感じました。

コーポレートチームとは

プレックスのコーポレートチームは2023年9月に誕生しました。業務内容ですが、社内で使われているコミュニケーションツールやCRM、MAツールの開発・運用になります。 プレックスの創業は2018年ですが、エンジニア組織ができたのは1人目の正社員エンジニアである石塚が入社した2021年になります。その間はビジネスサイドが主導して、業務委託やインターンのメンバーが開発を行っていました。

そのため、現状のシステムは技術スタックやコード品質にばらつきがあり、監視体制が整っておらずエラーが把握できないといった問題があり、それらの改修や改善を行なっています。

また、エンジニア起点でプロダクトを横断して作っていきたいデータ分析システムなどの開発も行なっています。長期的には社内で使用するCRMやMAツールの内製化も計画しています。

コーポレートや情シス、社内SEというと受け身の開発をしているイメージがありますが、プレックスのコーポレートチームは主体的な「攻めの開発」も行なっていきます。

入社1ヶ月経過しての所感

技術スタックの違い

プレックスでは標準の技術スタックとして、Ruby on RailsとNext.jsが定められています。 しかし前述の通り、現在の社内システムにはさまざまな技術スタックが使われています。

例を挙げると以下があります。

その他、APIもRESTだったり、GraphQLだったり…

私は今までエンタープライズ向けの開発が多く、言語としてはJavaC#を得意としていました。そのため動的型言語にイマイチ馴染めず四苦八苦しておりました。そこを助けてくれたのがGitHub Copilotです。AIの適切なアシスタントによって、技術スタック移行のハードルはかなり低くなりました。

またアプリの実行基盤としてHerokuやVercelを利用しています。前職ではデータセンターの自前のサーバーで処理していたため、そのデプロイの容易さにカルチャーショックを受けました。便利になりましたね。

業務への取り組みと支援

まず最初は既存システムの簡単な改修タスクから開始しました。そこで必要になる言語やフレームワークについて、CTOの石塚をはじめ同僚の方々がお勧めの書籍を教えてくださり、それを参考にしながら業務を進めました。

また、私が出したプルリクエストについて、かなり懇切丁寧に指導をしていただけました。ほんとうに感謝です! そのため、すんなりと業務に取り組むことが出来たと思います。

1on1の文化

プレックスでは1on1を重視しています。入社してしばらくの間はメンターと毎週1時間の定期的な1on1の時間があります。またそれ以外でも何か不明な点があれば、声を掛ければ話を聞いてもらえます。

出社について、プレックスでは在宅と出勤のハイブリットになっており、メンバーと毎日顔を合わせる訳ではありません。そこで1 on 1の機会にコニュニケーションが図れ、スムーズに溶け込むことが出来たかなと思っています。

これからやっていきたいこと

プレックスは創業から5年が経ち、社員数も300名近くまで成長してきました。そろそろ「0 → 1」のフェーズから「1 → 10」や「10 → 100」のフェーズに移行する時期なのかな、と個人的には思っています。 システムもMVP的な開発から、将来の拡張を見越した開発が求められる局面かと思います。

そこで私の今までの運用経験や技術的負債との格闘経験が役に立つのではないかと考えています。

おわりに

今回、初めてテックブログを執筆しました。プレックスはエンジニアの自由な意思を尊重して厚遇してくれていると感じます。そんなプレックスの雰囲気が少しでも伝わりましたでしょうか?

まだまだ書き足りないところもありますが、新しい人が続々と入ってきていますので、他の新人の入社エントリーに筆を譲りたいと思います。

最後にはなりますが、プレックスではソフトウェアエンジニアフロントエンドエンジニア、そしてコーポレートエンジニアを募集しています。

もしこの記事を読んで、一緒に挑戦してみたいと思った方がいましたら是非ご連絡をお待ちしています!!

dev.plex.co.jp

Kaigi on Railsの参加レポートと管理画面用のAPIを統合した話

はじめに

この記事は「技術カンファレンス Advent Calendar 2023 | 2枚目」の12日目です!

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

今回は10月27日・28日で開催されたオフラインイベント、Kaigi on Railsの参加レポートと、その中でのSMART BANK @ohbaryeさんの発表「管理画面アーキテクチャパターンの考察と実践」が同時期にPlex Job開発チームでも取り組んでいたリアーキテクティングと重なる部分があったため、発表内容を一部をお借りし、我々の取り組みについても紹介したいと思います。

Kaigi on Rails 2023の参加レポート

元々オンライン開催されていた時の登壇資料やアーカイブ動画を見たことがあったのでイベント自体は認知していました。 今回、初のオフライン開催であることや、会社でカンファレンスの参加費用補助制度もできたので、制度を活用して参加してみることにしました。

2日間、現地で講演を聞きましたが、どの発表も非常にわかりやすく、学びになるものでした。 特にRailsをプロジェクトで運用する中で発生するパフォーマンスや保守性の担保に関するものが多かった印象です。 Railsを採用していると立ち上げのスピードと引き換えに、システム規模の拡大とともにパフォーマンスや保守性の壁にぶつかることが多いです。 サービスのスケール時に技術選定から見直すこともあるかと思いますが、なるべくRailsで培った資産を有効に活用していきたい、そういった場合のノウハウが詰まっていました。

基調講演ではRailsコミッターであるzzakさんやbyrootさんの発表がありました。 お二人ともRailsへ携わるきっかけや、課題の特定と解決に向けた取り組み、OSSプロジェクトでの立ち回りで重要なことについて、経験を交えて紹介されていましたが、チームや個人としての成果を出す上では私達が普段プロダクト開発においても意識していることと重なる部分も多いと感じました。

また、イベントとしても初のオフライン開催とは思えないほどスムーズかつ丁寧な進行で、スポンサーブース、懇親会ともに終始楽しく参加することができました。 オフラインならではの熱気があり、私自身、刺激を多く受けて帰ってきました、改めてオフラインイベントのよさを感じた2日間となりました。

ちなみにESMさんのブースのガチャガチャでは#refineメソッドが当たりました。

Kaigi On Rails

さて、今回の講演の中で特に印象に残ったものの一つとして、SMART BANK @ohbaryeさん「管理画面アーキテクチャパターンの考察と実践」の発表があります。

プロダクト開発を行っていると社内向けの管理画面が必要になる機会が訪れます。 管理画面を開発する上で取られるアーキテクチャパターンを体系的化し、ビジネス要件とアーキテクチャ特性から採用したアーキテクチャと、それをRailsで設計・実装する上での工夫について非常にわかりやすく紹介されていました。

ちょうどKaigi on Railsの開催期間中に我々も管理画面のリアーキテクティングに取り組んでいたこともあったので、発表内容をお借りして、我々の取り組みについて紹介をしたいと思います。

社内管理画面のAPI統合

背景

私達も同じく、初期フェーズは仮説検証を優先し、管理機能を運用でカバーしつつ後追いで徐々に管理画面化を進める方法をとっていました。

我々の移行前のアーキテクチャパターンは以下です。

資料中の「マイクロサービスで共有データベースパターン」です。 エンドユーザー向けのサーバーと管理機能のユーザ向けのサーバーを分けるが、同一のDBを参照するというものです。 私達の場合もメリットとして挙げられている、「立ち上げ時の実装を楽にしたい」に加え「管理機能からの時間のかかるリクエストによって、エンドユーザー向けの機能に影響を与えないようにしたい」ことからこちらのパターンを選定した背景があります。

立ち上げ期は単純なCRUD操作を中心に機能要件としても複雑なものは必要なかったのですが、事業の成長とともに、複雑で事業上重要な要件を持つオペレーションの管理機能化や社内ユーザーの増加もあり、保守性や安定性がより求められるようになってきたところですが

  • デグレやすい
    • 依存モジュールの更新やCIの整備が放置されている
    • 単体テストやlinterの整備などが放置されている
  • 開発者のスイッチングコストが大きい
    • 同じドメインのモデル定義や実装を異なるコードベース間で同期させる必要がある
    • デプロイ対象のサーバーコンポーネントが多い

上記のような、課題が大きくなってきました。 安定性や保守性の要件に対して、立ち上げ期ではなくなってきていることや、当初のパフォーマンス面での懸念事項も徐々に改善できていることから、アーキテクチャの変更に踏み切ることにしました。

変更後のアーキテクチャ

資料中の「既存Backendだけ再利用しつつ管理機能はPDS順守パターン」です。 エンドユーザー向けのサーバーと管理機能向けのサーバー、参照先のDBは同じで、フロントエンドをエンドユーザーと管理機能の利用者で分けるというものです。

これにより、以下のようなメリットを享受することができました。

  • 同じドメインを扱うモデル、コードの再利用が可能になった
  • コードベースを統合したことにより、比較的メンテナンスされているコードベースのテストやCIにのっかることができ、保守性やテスト容易性などが向上した
  • サーバーコンポーネントが減ることによって保守・運用コストが削減された

統合に向けてやったこと

今回の統合で上記のようなメリットは得られつつも、統合時に試行錯誤したこと、一部妥協し今後の課題として残っているところがいくつかあるため、その中の一部を紹介したいと思います。

Plex Jobの管理画面の構築には以下を使用しています。

  • Ruby (3.2.2)
  • Rails (7.1.1)
  • graphql-ruby (2.1.6)
  • react-admin (4.10.2)
  • ra-data-graphql-simple (3.19.5)

GraphQLスキーマを共存させる上で

Plex Job開発チームでは、管理画面へ提供するAPIを統合先のエンドユーザー向けと同じくGraphQLで作成されていました。 そのため、React AdminのData Providerである、ra-data-graphql-simpleの仕様に合わせて、GraphQLのスキーマを既存のスキーマに統合する必要があり、統合にあたって考慮が必要になるポイントの一つでした。

GraphQL上のスキーマを共存させる

ra-data-graphql-simpleでは、対象のリソースに対して以下のようなSchemaを提供する必要があります。 以下は、README.mdにあるPostリソースを例とした場合の期待するスキーマです。

type Query {
  Post(id: ID!): Post
  allPosts(page: Int, perPage: Int, sortField: String, sortOrder: String, filter: PostFilter): [Post]
  _allPostsMeta(page: Int, perPage: Int, sortField: String, sortOrder: String, filter: PostFilter): ListMetadata
}

type Mutation {
  createPost(
    title: String!
    views: Int!
    user_id: ID!
  ): Post
  updatePost(
    id: ID!
    title: String!
    views: Int!
    user_id: ID!
  ): Post
  deletePost(id: ID!): Post
}

type Post {
    id: ID!
    title: String!
    views: Int!
    user_id: ID!
    User: User
    Comments: [Comment]
}

input PostFilter {
    q: String
    id: ID
    title: String
    views: Int
    views_lt: Int
    views_lte: Int
    views_gt: Int
    views_gte: Int
    user_id: ID
}

type ListMetadata {
    count: Int!
}

scalar Date

上記のようなスキーマを既存のスキーマに統合するにあたって、私達のコードベースでは以下のような点に注意する必要がありました。

  • Object Type名の競合
  • Input Type名の競合
  • Operation名(QueryやMutation)の競合
Object TypeやInput Type名の競合への対応

GraphQLサーバーはその仕様上、/graphqlという単一のエンドポイントのみを持ち、リソースはREST APIのようにパスではなく、Typeを定義することで表現します。 そのため、今回のように扱うドメインは同じではあるが、ユースケースとしては異なる複数のクライアントに同じリソースを返す際に名前が競合してしまいます。 GraphQLではスキーマにnamespaceの概念の導入するProposalも作成されていますが、導入されるには至っておりません。 今回は、書籍「PRODUCTION READY GRAPHQL」を参考にプレフィックスで明示的にnamespaceを定義する方法をとることにしました。

以下は、同じUserというリソースを扱う場合の例です。

# エンドユーザー向け
type User {
  ...
}

# 管理画面向け
type AdminUser {
  ...
}
Operation名(QueryやMutation)の競合への対応

リソース名をプレフィックス付きで定義すると

  • all_admin_users
  • _all_admin_users_meta

Operation名もリソースを踏襲することになるため名前の競合を気にする必要はありません。

ただし、graphql-rubyを使用している場合はMutationのResolverを定義するクラス名に注意する必要があります。 graphql-rubyではPayload Typeがクラス名を元に自動で書き出されることから、両クライアント向けに同名のMutationクラスが定義されている場合にPayload Typeが競合する問題がありました。 冗長ではありますが、Mutationのクラス名を、PrefixつきのPayload Typeが書き出されるように定義することにしました。

以下、例

module Mutations
  module Admin
    class CreateAdminFeature < GraphQL::Schema::Mutation
      ...
    end
  end
end

コードを共存させる上で

元々管理画面用にあったコードベースを統合するにあたって、管理画面用の定義であることが把握しやすい作りにしておきたいです。 SMART BANKさんの取り組みでも紹介されていましたが、私達もnamespaceでの分離を行っています。

以下、例

app/graphql/types/admin/admin_user_type.rb
module Types
  module Admin
    class AdminUserType < Types::BaseObject
      ...
    end
  end
end

今のところ、使用するModelは同じにしており、主にapp/graphql配下でnamespaceによる分離を行うようにしています。 SMART BANKさんでは、同じモデルを利用する場合は継承やコンポジションを使用し、管理画面特有の振る舞いに拡張させるなど、同じnamespaceによる分離でもより分離レベルを高める取り組みをされているようで、非常に参考になりました。

今後に向けて

名前空間の分離レベルを上げたい

前述した通り、現状だとモデル内でエンドユーザー向け機能のための振る舞いか、管理画面のユーザー向けの振る舞いかが分かりづらくなっています。 SMART BANKさんの取り組みのように、振る舞いを分離するような工夫をしていきたいです。

GraphQLのスキーマを共存させるためにとった一時的な対応の改善をしたい

こちらも前述した通り、名前空間が競合する可能性があるものにPrefixをつけて対応していますが、コードベースの名前空間との兼ね合いで定義が冗長になってしまっています。 また、Mutationクラスの命名をはじめ規則性が弱く一部把握しづらいコードになってしまっており

  • より柔軟なGraphQL向けのData Providerを持っていそうなRefineに乗り換える
  • 自分たちで名前空間の切り分けを行いやすいData Providerを実装する

など、引き続き改善に向けて検討を行っていきたいところです。

実行プロセスの分離を行いたい

資料中でもコードベースは同じでありつつ、プロセスを分けることによるメリットについて言及されていました。 Plex JobではHerokuからGKE Autopilotへのインフラ環境の移行を計画していることから、サーバープロセスを柔軟に配置することができるようになる見込みなので、合わせてチャレンジしていきたいです。

終わりに

今回、さらっとKaigi On Railsの参加レポートを兼ねて、弊社Plex Jobでの管理画面用のAPI統合の取り組みについてお話させていただきました。

統合は完了したもののまだまだ課題は多く残っています。 このような課題にチャレンジしていただけるソフトウェアエンジニアフロントエンドエンジニアを募集しています。

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

参考資料

【DevOps】開発の振り返りをアップデートした話

はじめに

こんにちは、プレックスの池川です。

2023年2月に「DevOpsの指標を開発の振り返りに活用しはじめた話」という記事をこのブログに投稿して、はや10ヶ月。10ヶ月の間に振り返りのやり方も変わってきました。

product.plex.co.jp

そこで今回の記事では、振り返りのやり方が10ヶ月前と比べて何がどう変わったのかを紹介したいと思います!

目次

エンジニア組織について

振り返りについて紹介する前に、プレックスのエンジニア組織について簡単に紹介します。というのも、振り返りの方法を見直すきっかけが「エンジニア組織の拡大」だったからです。

プレックスの開発体制は下記の画像のような事業部制を基本としています。エンジニアの人数は10ヶ月前と比べると、正社員が4名→6名インターン1名→3名に増えました。また、コーポレートマーケという社内システムの開発や管理を行う事業部も立ち上げられ、現在エンジニアは各々3つの事業部に所属しています。

開発体制

以前はエンジニア全員での振り返りを行っていましたが、各事業部ごとにサービスがあり取り扱っているドメインも異なることから、私が所属しているプレックスジョブ開発チームでも振り返りを導入するようにしました。

プレックスジョブ開発チームでの振り返り

振り返りMTGについて

プレックスジョブ開発チームではスクラムを採用しており、1スプリントを1週間としています。振り返りもスプリント単位で行っており、スプリント開始のタイミングでMTGを行い前スプリントの内容を振り返っています。 下記が振り返りの内容です。

  1. KPT
    • 事前に振り返りシートを共有し、各メンバーにKPT用のJamboardに今週のアクションや課題を記入してもらう
    • Jamboardに各自作成してもらった今週のアクションや課題をKeepとProblem、Tryに振り分けて発表する
    • 全員のKeepとProblemが分類でき次第、Tryをタスク化する
  2. 開発のパフォーマンス改善
    • Four Keys の指標をもとに前スプリントのパフォーマンスを振り返り

KPTについて

KPTを用いた振り返りは元々エンジニア全体で行なっていましたが、事業部単位で行うようにしました。

Jambordの作成と共有はGASを使って自動化しており、MTGの前日にSlackのエンジニアチャンネルで共有されるようにしています。

実際のMTGで仕様したJambordです。

Jambord

KPTを行うことでポジティブ、ネガティブなことに関わらずメンバー間で情報共有ができるほか、課題の早期発見と解決にもつながるので振り返りにオススメの方法です!

開発のパフォーマンス改善について

次にFour Keysを用いたパフォーマンスの振り返りについて、どのように変わったか紹介します!

Four Keyesの指標は元々集計していたものの、振り返りの指標としてあまり運用できていなかったため、振り返りのMTGで運用できるようにダッシュボードや運用方法の見直しを行いました。

まず、ダッシュボードを Google Looker StudioからRedashに移行しました。Redashは他のプロジェクトでも使用されていて、データの可視化や取り回しがしやすく、関係者が全員アクセスできるといった点で採用しました。

現在のダッシュボードです。

現在(2023年10月時点)のダッシュボード

集計している指標は10ヶ月前と同じデプロイ頻度リードタイムですが、それぞれの指標についてGoogleのパフォーマンスレベルをもとに下記の目標を定めています。

  • デプロイの頻度:スプリント平均で一日一件以上
  • リードタイム:120時間(5日以内)

集計フローはこちらです。

  1. GitHub API から取得したデータを加工して BigQuery に保存するスクリプトを実行
  2. Redash で Google SQL を実行し、必要なデータを取り込み
  3. 取り込んだデータを Redash でグラフ化してダッシュボードに表示

MTGではダッシュボードを確認し、目標が達成できていない項目については、プルリク単位で振り返りを行い原因の特定と改善策を話し合います。 数字をベースに振り返りを行うことで、KPTとは違ったアプローチで現状把握や課題の発見ができるようになりました。

運用する中で効果のあった改善策の一例を紹介します。従来、パッケージのバージョン管理をDependabotで行なっていましたが、プルリクが大量に作られることから対応が後回しとなり、結果、リードタイムが長くなっていました。そこでマイナーバージョンのプルリクをまとめて作成してくれるRenovateに移行することにしました。導入した結果、リードタイムの平均(コミットされてからデプロイされるまでの時間)は268時間(11日)130時間(5.4日)と半分になり、大幅にリードタイムが改善されました。

リードタイム_平均

次に、エンジニア全体で行なっている振り返りについて紹介します!

エンジニア全体での振り返り

エンジニア全体の振り返りは元々週一回行っていましたが、隔週で金曜日に1時間程度、定例MTGを行うように変更しました。

従来、MTGではKPTを行いアクションや課題間を共有していましが、振り返りの方法を見直す中でKPTは廃止して各々が開発する中で得た学びをシェアする時間を設けました。

メンバーはそれぞれあらかじめNotionに共有したい学びをまとめておきMTGで順番に発表していきます。

振り返りシート(一部抜粋)

開発する中で得た学び開発中に遭遇したバグや、新しい技術を試してみた話、便利なツールの紹介など興味深いトピックが多く、知識の共有だけでなくエンジニア全体の結束を高めることにも繋がっていると感じています。

さいごに

今回の記事では、プレックスのエンジニア全体とプレックスジョブ開発チームでの「振り返り」の取り組みに関して紹介させていただきました。

前回の記事から10ヶ月が経ち、振り返りの継続実施はできるようになりましたが、今後も組織や事業の成長に合わせて随時やり方を見直し柔軟に取り組んでいくことが必要だと考えています。

振り返りの取り組みやFour Keysをはじめとした指標の活用の変化に関しても引き続きアップデートがあれば、本ブログで紹介していきます。

今回紹介したような開発の効率化や振り返りに少しでも興味を持っていただけた方はぜひ一緒に取り組みましょう!

dev.plex.co.jp

プレックスのエンジニア組織初となるオフライン勉強会を開催しました!

匠技研工業×プレックス ミートアップ

こんにちは、株式会社プレックスの石塚です。 2023/08/30(水)にプレックスのエンジニア組織では初めてとなるオフライン勉強会を開催したので、今回のブログでは勉強会の様子を少しでもお伝えできればと思います。

plex.connpass.com

オフライン勉強会を開催した背景

勉強会のレポートの前に、なぜオフラインの勉強会を開催したのかについても簡単に触れておきます。理由は大きく分けて2つあります。

1つ目は個人にとってリアルな繋がりを広げることができる場所を作っていきたいということです。コロナの影響もあり、IT業界ではリモートワークがより一般的になってきました。これは不可逆な変化であり、インターネットの進化によってますます加速していく流れであると感じています。しかしながらそうしてリモートワークがより一般的となった社会では、リアルな繋がりを作れる場所の重要性はますます高まってくるはずです。事実、今年の始めくらいからはエンジニア界隈でもオフラインイベントが目立つようになってきました。

2つ目が社内のエンジニアが登壇したり、外部のエンジニアと交流することによって、成長機会として活用してもらいたいということです。どうしても普段と同じ人と、同じ仕事を続けていると、視野が狭くなってしまったり、偶然による新たな発見が得づらくなってしまいます。意図しない出会いや外部からのフラットな目線を入れることで、普段の仕事の中でも工夫や違った視点からの提案が生まれることを期待しています。さらにはこういった社内のイベントでの登壇をきっかけに、大きなカンファレンスやイベントで登壇する方が出てきてくれたら嬉しいなと思っています。

当日の様子

話が少し脱線してしまいましたが、本題の勉強会の様子に入っていきます。勉強会は共同開催している匠技研工業さんのオフィスで実施しました。今年の6月に移転されたばかりということもあって、綺麗なオフィスで、弊社のメンバーもテンションが上がっていました。

イベントスペースは執務室に机と椅子を用意して設置。勉強会のために大きめのモニターも購入していただきました。ありがたい...🙏

準備中の様子

タイムテーブルは

  1. テーブルごとに分かれて乾杯、自己紹介
  2. プレックス 種井による発表
  3. 匠技研工業 井坂による発表
  4. 懇親会

という流れでした。

プレックス 種井による発表

弊社エンジニアの種井からは「Plex Jobと技術負債のマネジメント」というテーマの発表がありました。 Plex Jobの事業やプロダクトの特性を踏まえて、どうやって技術的負債と向き合ってきたかが、0→1の立ち上げフェーズと1→10のグロースフェーズでどのように変わっていったかというお話でした。

プレックス 種井による発表

手前味噌ではありますが、プレックスでは技術的負債を認知→蓄積→返済していくというプロセスを整理しており、仕組みとして技術的負債を返済しているという点が印象的でした。

技術的負債に対する取り組みとサイクル

匠技研工業 井坂による発表

匠技研工業の井坂による発表は「高速なMVP検証を支えた技術的負債とその解消」でした。

匠技研工業 井坂による発表

シードからシリーズAとMVP検証を重ねる中で、検証スピードを高速化するために匠技研工業が意図的に抱えていった技術的負債が、技術的負債の4分類の中でどれに属するかを参加者の皆さんに考えてもらって手を挙げてもらうなど、インタラクティブな発表でした。

技術的負債の分類

中にはパブリックな場では公開できないような内容もあり、オフラインイベントならのライブ感がありました。

懇親会

懇親会は運営が事前に用意していた発表に関連したテーマをベースに、5, 6人でテーブルごとに分かれたグループでディスカッションをする形式でした。テーマは「技術的負債に取り組む上でどうやってチームの理解を得ているか」であったり、「今までに経験した大規模なリプレースの思い出」などがありました。

プレックスや匠技研工業は比較的若い会社、プロダクトでしたが、参加者の中には10年近く運用を続けているようなプロダクトに携わっている方もいたり、組織が成長して大規模化して後のフェーズの方もいたりと、また違った悩みや課題に触れることができたのも新鮮でした。

次回のイベントについて

プレックスでは匠技研工業さんとのイベントを、3ヶ月に1回程度を目安に継続的に実施していく予定です。まだまだ試行錯誤の段階なので、テーマや形式は変わっていくかと思いますが、温かい目で見ていただいて、ご参加いただけると嬉しいです。

また次回イベントの情報の通知も来るようになるので、connpassページからぜひメンバー登録をお願いします。

plex.connpass.com

プレックスジョブが目指す世界と課題

はじめまして、株式会社プレックスの平井と申します。

私は、一般的にプロダクトマネージャーとWebマーケティングと言われる役割を担当しており、 インフラ産業に従事するエッセンシャルワーカー向けの転職・採用プラットフォーム「プレックスジョブ」の改善や集客に関わる意思決定や施策の実行を担当しております。

今回の記事は、プレックス及びプレックスジョブにご興味を持っていただいた方に、企業とプロダクトが目指している世界、それに対しての現状や課題、弊社が候補者様に提供できるものについて少しでも理解が深まる記事になればと思っております。

簡単な自己紹介

主題をお話する前に簡単に私の経歴をお伝えすると、新卒でナイル株式会社というデジタルマーケティングを主軸にしたコンサル・事業を行っている会社に入社し、SEOを中心としたデジタルマーケティングコンサルティングを担当した後、プレックスに5人目のメンバーとして入社しました。

プレックスに入社後は、下記のような役割を担当してきました。

  • 求職者様の集客するためのメディアの立ち上げ
  • 自社採用・人事機能の立ち上げ
  • 採用広報機能の立ち上げ
  • 人材紹介事業部の業務改善
  • 新規領域の人材紹介事業の選定

個人としてはあまり役割にこだわりがあるタイプではなく、目的に対して自分がバリューを発揮できるのであればOKというタイプのため、このような経歴を歩むことになりました。

プレックスが5人→150人くらいの企業になるまでの様々な酸いも甘いもある経験を積み重ね、今はプレックスジョブで目指す世界の実現に向けて、開発、セールス、カスタマーサクセス、他事業などとの連携を取りつつ、プロダクトや集客の改善に取り組んでいます。

プライベートでは最近はとうとうゲーミングPCを購入し、valorant、信長の野望civilizationの練習に勤しんでおります。

プレックスという企業がどういう世界を目指しているか

まずプロダクトが目指す世界のお話の前に、プロダクトの上段の概念にある企業がどういう世界を目指しているのか、という点についてお伝えできればと思います。

ざっくり「自分たちが解決できると仮説立てられる中で、大きな課題を手法や領域に縛られず解決していこう」という、いわゆるマーケットの課題から事業を始めるタイプの企業だと大枠で捉えていただければ良いかと思います。

具体的に、現在のプレックスは「日本を動かす仕組みを作る」というミッションを掲げており、下記のような事業を展開しています。

  • 物流領域の人材紹介事業
  • エネルギー領域の人材紹介事業
  • 製造領域の人材紹介事業
  • エッセンシャルワーカーのダイレクトリクルーティングサービス(プレックスジョブ)
  • M&A仲介事業
  • SaaS事業

ミッションを少し具体化して解釈すると、「日本を動かすくらいのインパクトがある産業の課題に対して、事業という仕組みを使ってより良くしていく」といった意味があり、現に今取り組んでいる事業も、領域やビジネスモデルに縛られず、自分たちが解決すべき、解決できると信じる領域に対して始めた事業になっています。

今後企業の成長次第ではミッションの変更もあるかとは思いますが、プレックスが現時点で見えている将来としては、多種多様の産業や課題に対して、ビジネスで解決していくことを続けていこうと考えている企業で、今後も新たな事業・プロダクト・サービスを生み続けていこうとしています。

プレックスという企業全体にご興味がある方は採用ピッチ資料をご覧ください。

プレックスジョブの目指す世界と現在地

「日本を動かすくらいのインパクトがある産業の課題に対して、事業という仕組みを使ってより良くしていく」企業の中で、プレックスジョブが目指す世界は「エッセンシャルワーカーNo.1の採用プラットフォーム」になります。

具体的に「エッセンシャルワーカー」とは、物流、エネルギー、製造など人の生活の基盤となる産業で働いている方々を指しています。エッセンシャルワーカーを採用するすべての企業様、すべてのエッセンシャルワーカー様にとって「プレックスジョブを使えば、早く、効率的に、双方の希望を満たした採用・転職ができる」という世界を目指しています。

エッセンシャルワーカーは日本全国で3,100万人、エッセンシャルワーカーが関わる産業の市場規模は100兆円を超えると言われており、まさしく日本を動かしている方々、産業に対して、採用・転職の課題を解決するプロダクトになるべく、プレックスジョブが存在しています。

エッセンシャルワーカーの市場規模

2023年7月時点、弊社では累計約38万人の求職者様からの登録がありますが、エッセンシャルワーカー全体で見ると約1%、契約事業所数も12,000と、市場の大きさを鑑みるとNo.1採用プラットフォームへの道のりとしてはまだスタート地点とも言える状態にあり、多くの課題、成長余地が残されています。

ただ、エッセンシャルワーカーの採用市場の状態としては、人口減少や高齢化で採用が難しくなった流れに応じて、変化が起き始めている時期と言えます。

恐らく、この記事を読まれている方はIT系企業などに属していたり、営業/マーケティング/エンジニアといった職種の方かと思いますが、そういった方々が転職する際は人材紹介、ダイレクトリクルーティング、リファラル、SNSをメインの転職手法として活用し、ハローワークや求人媒体で転職先を探すといったことは少ないかと思います。

IT系職種を採用する企業側もハローワークや求人媒体だけでは採用が難しく、様々な採用チャネルを駆使してなんとか採用計画を達成するような状況です。

しかし、物流のドライバー採用では、ハローワークでの求人募集、紙/Webの求人広告が未だに多く活用されており、人材紹介やダイレクトリクルーティングは聞いたこともないという企業様や求職者様の方が割合としては多いです。

歴史を遡ると営業やエンジニアなどの職種も、日本の労働人口が多く、採用市場の企業側のパワーが強かった時代は、ハローワークや求人媒体がとても強力な採用手法だったと思いますし、ダイレクトリクルーティングという概念も存在していませんでした。

しかし、労働人口の減少、採用競争の過激化、テクノロジーの進歩に伴い、企業と働き手のパワーバランスや情報格差に変化が起き、採用手法が多様化したという歴史があると捉えています。そして、このような採用手法の変化が、エッセンシャルワーカーが働く領域にも今後起こると考えています。

人口減少と社員の平均年齢の高齢化が重なり、従来の採用手法では採用が足りず、企業が働き手に対して能動的に採用活動を仕掛けていくトレンドが、ドライバーや電気主任技術者、製造職などの領域に広がっていく中で、その先頭をプレックスジョブが担える可能性があります。

数多の進歩により物質的に豊かになった現代において、人々の当たり前になっている活動・行動・トレンドを変えることができる領域はそう多くはないと個人的には感じていて、その大きな変化を動かす中に身を投じる経験は一定のやりがいや楽しみがあるのではないかと思います。

そして、エッセンシャルワーカーのNo.1採用プラットフォームというだけでも、とても先の長い話ではありますが、日本全体で見たマクロトレンドも踏まえると、プレックスジョブの「エッセンシャルワーカーのNo.1採用プラットフォーム」というミッションも更新される可能性が高いと見立てています。

現在のエッセンシャルワーカー、インフラ領域は「人が足りないから採用をしたい」という文脈が強いですが、人口減少や技術進歩が進むに連れて、

  • 経験者が採用できないから、未経験でも活躍できる教育環境を整えなければいけない
  • 採用しても退職を減らさなければそもそもの労働人口が足りない
  • 退職が抑えられても労働人口が足りないから業務を効率化が必要

といったように、大きなトレンドに対してマーケットの課題認識や緊急度が変化していくことが想定されます。

そのようなマーケットの変化に合わせて、採用というプラットフォームから定着、働き手のパフォーマンス向上、業務効率化など、プロダクトが提供する価値の範囲、大きさが広がっていく可能性を秘めていると考えています。

また、採用というアプローチから入ることで働き手と企業との関係性、データなどを集めることができますので、採用以外の事業に取り組む際に顧客の課題の解像度を上げる上でも、より早く、濃いインプットや示唆を得ることができます。

今後、様々な可能性の広がりを秘めたエッセンシャルワーカー、インフラ領域というマーケットでは1つずつ大きな山を乗り越えていかなければならないため、まず最初に目指す世界として、エッセンシャルワーカーの採用No.1プラットフォームになることが現時点でのプロダクトのミッションとなっております。

プロダクトミッション実現に向けた直近の登り方

プロダクトのミッションに向けて、そこに到達するための道筋は無限にありますが、その中から現時点で最も速く到達できると信じられる仮説が、直近の事業戦略、プロダクト戦略となります。

現時点で、という但し書きをつけているのは、プロダクトのフェーズや組織のフェーズ的に、直近1ヶ月で得たインプットや、新たに入ったメンバーの活躍により、より良い仮説が出てくることが多いためです。

直近取り組むべき仮説としては、「企業様の採用活動において、サービス利用のハードルを下げる」というポイントをテーマとしています。

「採用No.1プラットフォーム」は企業様と求職者様という2者のユーザーのニーズが満たされることで達成できるミッションになっています。そのため、両方のニーズを同時に満たすことを考えると、逆にどちらも中途半端になってしまうリスクがあります。

そこで2023年の第1四半期では求職者様に向けた集客やプロダクトの改善をメインに進めて一定の進捗があったため、2023年の第2四半期では企業様に向けたプロダクトの改善を進めていこうという方針になっています。

「サービス利用のハードルを下げる」という方針に決めた理由としては、大前提としてプロダクトやサービスモデルに対して馴染みがない企業様がとても多いからです。

そのため、少しでも分からないことや既存のオペレーションよりも大変だと感じると、離脱が起こってしまう可能性が高く、いち早く新しいサービスを取り入れていただいている企業様が離れてしまうことは今後のマーケットへの影響を踏まえても避けておきたいところです。

そこで、まずはダイレクトリクルーティングというプロダクトに馴染みを持っていただき、今の採用活動のオペレーションよりも早く、効率的に採用ができる体験をしていただくことを1歩目として設定し、直近の方針としています。

具体的には、求職者様とのメッセージのやり取りを行うメッセージ機能の改善、選考の進捗を確認・記録できる選考管理画面の使いやすさの改善、採用活動のオペレーションを効率化できる機能の開発などを中心に取り組んでいきます。

一定の機能開発が進んだ後は、ドライバーなど現在弊社がメインで支援している職種以外のエッセンシャルワーカーへの支援を広げ、エッセンシャルワーカー内での人員配置の最適化を行っていくなど、プロダクトが与える影響範囲の拡張を進めていこうと考えています。

プロダクトミッション実現に向けての課題

大きく分けて3つの課題感があります。 1つ目は、「企業様、求職者様からダイレクトリクルーティングという手法及びプロダクトの理解を得る」ということです。

顧客にとって新規性の高いサービスは、なんとなく怪しく見えたり、費用対効果などが読みづらかったりと導入の難易度が高いです。そのため、セールスやマーケティング活動を通じてプロダクトの価値を理解してもらい、実際に使って価値を享受する経験を積んでもらうことが重要になります。

その中でプロダクトチームとして取り組むポイントは、「軽く触ってみたけどよくわからないな」「使ってみたけど他の採用チャネルより大変だな」などといった、新しいプロダクトに馴染む1歩目のハードルを乗り越えることがとても重要になると考えています。

2つ目は「産業、職種ごとの特徴や傾向を捉えてプロダクトを最適化する」ということです。

具体的には、ドライバーを採用したい企業様と電気主任技術者を採用したい企業様では知りたい求職者様の情報が異なっています。同じように求職者様側にとっても、企業様について知りたい情報がドライバーと電気主任技術者では異なります。

そのようなユーザーのセグメントごとに違うニーズを、プロダクトとしてどのように捉え、機能や実装を行っていくかという点は、弊社のプロダクトが成長するに連れて出てくる課題になると考えています。

また、トラックドライバーから製造オペレーターへなど、異職種、異産業への転職というのも増えてくることが予測されます。その際の企業様・求職者様データベースの取り扱いをどうするか、管理画面をどうするかなど、将来的な広がりを踏まえつつ、短期的に必要なもの、長期短期のバランスを捉えた開発が必要になります。

3つ目は「顧客が想定していなかった選択肢の提案を行えるようになる」という点です。

企業様、求職者様は同じ産業や職種への知見がとても深いです。それは、基本的に同産業同職種への転職がスタンダードな世界で、ドライバーはドライバーへ転職をするというのが一般的なためです。

そのため、企業様もドライバーであればどういう物を運んでいたら自社にフィットするかなどは、過去の経験から判断することができます。ただし、ドライバー以外の仕事をやっていた人が自社で活躍できるかという点については、実際採用や入社の経験が多くなく、判断が難しいケースがあります。

そこで、プレックスジョブが得てきたデータを活かして「こういう職種の人はドライバーで活躍する傾向がある」などの提案を行えると、企業様に対して今までの採用手法では出会えなかった人に出会える可能性があります。また、求職者様も同じく、自分で探していたら出会えなかった企業に出会う機会をプレックスジョブが提供できるようになるとミッション達成により近づくのではないかと思っています。

プレックスジョブプロダクトチームで働く方に弊社が提供できるもの

弊社及びプロダクトとしての現在、想定している未来についてお話してきましたが、個々人のキャリアや人生において何を提供できるかについて、あくまで私の主観的な話にはなりますがお伝えできればと思います。※報酬面などは他で記載があるので、どちらかというと非金銭報酬や定性的なお話をメインにさせていただきます。

マーケットに新しい常識を作る経験

これは前述した通り、ダイレクトリクルーティングが浸透していないマーケットに普及していくという文脈で、影響や変化の大きさ自体にやりがいを感じる方にとっては面白い経験になると思っています。

マーケットインでビジネスを構想し、エンジニアリングで実現する組織

せっかく開発したプロダクトや機能も使われないと事業を継続して運営していくことも、改善を回すことも、価値を生み出した実感も感じづらいものです。そうならないようにセールスやマーケティング、プロダクトマネージャーがビジネスとしてニーズがあるかどうかを検証していきます。

ビジネスサイドとエンジニアリングサイドという分断はプレックスにはなく、「顧客への価値提供とビジネスとして成り立つか」を目的とした1つの組織であり、その中の役割分担があるという考え方の組織になっているため、優劣や貴賤はなく、相互に尊重しあい、目的達成のために向かう組織になっていると感じています。

ビジネスモデル、マーケットごとの違いを知ることで、自身の知見に深みを出せる

ビジネスモデルやマーケットが異なるものの、セールス、マーケティング、開発などの職種は共通して存在しています。例えば、同じ「セールス」という職種にしても、どういう営業リストを作るか、どういう営業トークスクリプトを作るかなどは、顧客の属性、事業・プロダクトの状態などによって大きく異なります。

そのような各事業での成功施策、失敗施策の背景や施策の具体をインプットし抽象化すると、成果への関連性が高い共通要素が浮かび上がってきます。そして、共通要素を自分が担当する事業やプロダクトに当てはめて改善と検証を繰り返すことで、徐々に成功確率が高まっていき、自身が担当する役割や業務における再現性を持てるようになり、新たな事業やプロダクトであっても、初速から精度高く施策を当てられるようになってきます。

プレックスでは複数事業経営のスタイルのため、役割や業務の学びのサイクルを速く、大量にインプットすることができるため、知的好奇心や成長実感を得やすい環境になっているかと思います。

最後までお読みいただき、ご興味を持っていただけた方に

企業としてもプロダクトとしてもまだまだ発展途上ではありますが、目指している世界や環境についてご興味をお持ちいただけた方はぜひ一度PLEXメンバーとお話の機会をいただけたら嬉しいです。

複数の事業や職種での募集がありますので、プレックスジョブ以外での可能性も含めてお話ができると思いますので、気軽に下記からご応募ください!

エンジニア職向けカジュアル面談フォーム

docs.google.com

ビジネス職求人情報

plex.co.jp