有名テック企業の技術ブログを、ひとつのフィードで。
フィード
31件
はじめに こんにちは、タイミーでエンジニアをしている徳富(@yannKazu1)です。 タイミーではメインサービスのバックエンドを Rails で開発しています(Go を採用しているプロダクトもありますが、本記事では Rails を前提とします)。 突然ですが、皆さんのチームでは CI の待ち時間、気になっていませんか? 「Push した、コーヒー淹れた、戻ってきた、まだ回ってる……」みたいな経験は、開発者なら一度はあるのではないでしょうか。 本記事では、そんな状況を改善するために GitHub Actions 上のテスト実行パイプラインで取り組んだ 3 つの高速化テク を紹介します。どれも「知っていれば明日から試せる」くらいの温度感なので、気軽に読んでいただければと思います。 1. キャッシュの保存先を GitHub Cache から S3 に移行 課題: actions/cache が安定して速くない 最初にぶつかった壁が actions/cache の速度でした。vendor/bundle(数百 MB〜1 GB 超)の save/restore でやたら時間がかかることがあり、リストアだけで数分待たされる場面がちょくちょくありました。これはセルフホストランナーに限った話ではなく、GitHub ホステッドランナーでも起きます。 実際、公式リポジトリにも Extremely slow cache on self-hosted from time to time という Issue が立っていて、セルフホスト・GitHub ホステッド問わず同様の報告が寄せられています。 さらに私たちの場合、AWS 上のセルフホストランナー を使っているのでなおさらです。actions/cache のバックエンドは Azure Blob Storage のため、セルフホストランナーからだとインターネット経由のアクセスになり、スループットが 約 20 MB/s まで落ちる ケースも報告されています(Actuated Blog)。突発的に遅いうえに経路も遠い——これでは安定した速度は望めません。 容量面でも、リポジトリあたり 10GB の制限があります。また、7 日間アクセスのないキャッシュは自動削除されます。その結果、ブランチが増えるとすぐに上限に達し、必要なキャッシュが消えてしまうのも地味にストレスでした。 解決策: runs-on/cache で S3 をバックエンドに そこで [runs-on/cache](https://github.com/runs-on/cache) を導入し、キャッシュの保存先を 同一リージョン(東京)の S3 バケット に切り替えました。 前述のとおり、セルフホストランナーで actions/cache を使うとスループットが ~20 MB/s まで落ちるケースがあります。一方 runs-on/cache は同一リージョンの S3 を使えるため、200 MiB/s 以上 のスループットが出ます(公式ドキュメント)。単純計算で 10 倍近い改善 です。 actions/cache とインターフェースがそのまま同じなので、uses: を差し替えて環境変数を 1 つ足すだけで移行できました。 # .github/actions/setup-ruby-with-s3-cache/action.yml - name: Restore cache uses: runs-on/cache@v4.2.3-r2 env: RUNS_ON_S3_BUCKET_CACHE: your-gha-cache-bucket with: path: "**/vendor/bundle" key: bundle-v1-${{ runner.os }}-${{ inputs.ruby_version }}-${{ hashFiles('Gemfile.lock') }} restore-keys: | bundle-v1-${{ runner.os }}-${{ inputs.ruby_version }}- bundle-v1-${{ runner.os }}- なぜ runs-on/cache を選んだか S3 をキャッシュバックエンドにする方法は他にもあります(tespkg/actions-cache、whywaita/actions-cache-s3、自前の aws s3 cp スクリプトなど)。その中で runs-on/cache にした決め手はこのあたりです。 環境変数 1 つで切り替え: RUNS_ON_S3_BUCKET_CACHE を設定するだけで S3 バックエンドに切り替わる 自前実装が不要: 圧縮・展開・キャッシュキーのマッチング・フォールバックなど、地味にめんどくさい部分を全部やってくれる 容量無制限: S3 なので 10GB の制限もキャッシュの自動削除もなし キャッシュキーの設計 キャッシュキーは 3 段階のフォールバック構造にしています。 bundle-v1-Linux-3.3.6-<Gemfile.lock のハッシュ> ← 完全一致(最速) bundle-v1-Linux-3.3.6- ← Ruby バージョン一致 bundle-v1-Linux- ← OS のみ一致 完全一致しなくても、部分一致したキャッシュをリストアして bundle install すれば差分の gem だけで済みます。ゼロからインストールするより圧倒的に速いので、新しいブランチでもほぼキャッシュが効く状態を維持できます。 OIDC 認証で安全に S3 にアクセス AWS へのアクセスには OIDC 認証 を使っています。長期的なアクセスキーをシークレットに保存しなくて済むので、セキュリティ面でも安心です。 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: arn:aws:iam::123456789012:role/your-gha-role aws-region: ap-northeast-1 2. マイグレーション結果をまるごとキャッシュ 課題: 毎回のマイグレーションが地味に重い テストジョブは毎回データベースをセットアップします。ここで問題になったのが、マイグレーション数が数百を超えてくると rails db:create db:schema:load だけで 数分かかる ということ。 「schema:load だからすぐ終わるでしょ?」と思いきや、テーブル数が多いとそうでもないんですよね。 解決策: MySQL のデータディレクトリごと S3 にキャッシュ 発想を変えて、マイグレーション済みの MySQL データディレクトリ (/var/lib/mysql) をまるごと S3 にキャッシュ することにしました。要は「マイグレーション済みの DB をそのまま持ってくれば、マイグレーション自体を省略できるよね」という作戦です。 仕組みの全体像 【キャッシュの生成】 【キャッシュの利用】 master ブランチ feature ブランチ db/migrate/** 変更 テストジョブ起動 or 毎日定時 │ │ ▼ ▼ S3 からキャッシュをリストア MySQL 起動 → ./tmp/mysql_data に展開 │ │ ▼ ▼ rails db:create db:migrate MySQL 起動(データマウント済み) │ │ ▼ ▼ ./tmp/mysql_data を S3 に保存 rails db:migrate(差分のみ) │ ▼ テスト実行 キャッシュの生成: master で定期的に焼き直す master ブランチでマイグレーションファイルが変更されたとき、または毎日定時に、専用のワークフローがキャッシュを更新します。 # .github/workflows/update-migration-cache.yml on: push: branches: [master] paths: - 'db/migrate/**' - 'db/schema.rb' - '.github/workflows/update-migration-cache.yml' - '.github/actions/migration-hash/**' schedule: - cron: '0 2 * * *' # 毎日 UTC 2:00(JST 11:00)に実行 workflow_dispatch: # 手動実行も可能 やっていることはシンプルです。 MySQL コンテナを起動(データディレクトリを ./tmp/mysql_data にマウント) rails db:create db:migrate でフルマイグレーション実行 ./tmp/mysql_data をまるごと S3 にアップロード - name: Run database migration run: bundle exec rails db:create db:migrate - name: Save migration cache uses: runs-on/cache/save@v4.2.3-r2 env: RUNS_ON_S3_BUCKET_CACHE: your-gha-cache-bucket with: path: ./tmp/mysql_data key: test-${{ runner.os }}-${{ runner.arch }}-mysql${{ steps.migration-hash.outputs.mysql_version }}-${{ runner.environment }}-db-migration-${{ steps.migration-hash.outputs.hash }} キャッシュキーの設計: 何をキーに含めるかが大事 キャッシュキーには地味に気を使っています。 test-Linux-X64-mysql8.0.28-self-hosted-db-migration-<db/schema.rb のハッシュ> │ │ │ │ │ OS ARCH MySQL Ver ランナー環境 スキーマハッシュ ポイントは db/schema.rb のハッシュを含めていること。マイグレーションの内容が変われば schema.rb も変わるので、自動的に新しいキャッシュが生成されます。MySQL バージョンやアーキテクチャもキーに入れているのは、バイナリ非互換でハマらないための保険です(一度やらかしました……)。 <h3 id="キャッシュの利用-Composite-Actio
こんにちは、株式会社タイミーでMLOpsエンジニアをしているKYです。普段はMLプラットフォームの構築・運用を担当しています。 実務の中でコンテナイメージのサプライチェーンセキュリティ強化を進めており、その一環として Docker 社が提供する「Docker Hardened Images(DHI)」の実装を辿る機会がありました。 その際、実際の定義ファイルを見て、少し驚きました。コンテナのビルド定義といえば「Dockerfile」が当たり前だと思っていたのですが、DHI の定義はなんと YAML で書かれていたのです。 「なぜ Dockerfile ではないのか?」と定義の読み方を追いかけていくうちに、BuildKit のアーキテクチャに行き着きました。この記事では、DHI の仕組みを通じて、私たちが普段の Dockerfile 運用で押さえるべきポイントを再確認したいと思います。 ビルド定義の主役は「Frontend」 BuildKit は、「定義を解釈する部分(Frontend)」と「実際にビルドを実行する部分(Backend)」に分離しています。Frontend は、入力(Dockerfile や YAML)を BuildKit の中間表現(LLB)に変換する役割を持ちます。 ここで鍵になるのが、ファイル先頭のコメント行 # syntax=... です。BuildKit はまずこの1行を読み、どの Frontend で後続を解釈するかを決めます。つまり、Docker 公式が推奨しているのに見落とされがちな以下の1行は、単なるコメントではなく「このファイルは公式の Dockerfile Frontend で解釈してほしい」という宣言です。 # syntax=docker/dockerfile:1 一方で DHI の定義ファイルを開くと、YAML の1行目に次の指定があります。 # syntax=dhi.io/build:2-debian13 YAML も # をコメントとして扱うため、BuildKit から見れば「# syntax= から始まるビルド定義」という意味で入口は同じ。その後の中身を YAML として解釈するのは、差し替えられた DHI Frontend の仕事というわけです。 DHI は何をしているのか:YAML をコンパイルする DHI の定義ファイル(YAML)は、RUN apt-get... のようにといった手順を重ねるのではなく、「最終的に何を入れるか」という状態を宣言します。 【DHI の YAML 定義例(実際の定義ファイルからの抜粋)】 # syntax=dhi.io/build:2-debian13 name: Debian 13 Base image: dhi.io/debian-base variant: runtime platforms: - linux/amd64 - linux/arm64 dates: release: "2025-08-09" end-of-life: "2028-08-09" contents: packages: - '!libelogind0' - '!mawk' - '!original-awk' - base-files - bash - ca-certificates - coreutils # ... 以下、ベースに含めるパッケージの列挙が続く accounts: run-as: nonroot users: - name: nonroot uid: 65532 gid: 65532 cmd: - /bin/bash いくつかのフィールドに注目してみます。 contents.packages: !mawk のように ! プレフィックスを付けると「明示的に含めない」パッケージを宣言できます。削除手順を書くのではなく、最初から「入れない」と表明する点が Dockerfile との大きな違いです。 accounts.run-as: nonroot: 実行ユーザーを非 root に固定する宣言で、Dockerfile の USER 命令に相当します。Dockerfile のように RUN useradd ... といったユーザ作成手順を書く必要はなく、「誰で動かすか」という状態だけが残る点が特徴です。 dates.end-of-life: イメージのライフサイクル終了日まで定義に含まれており、運用上の管理情報もビルド定義の一部として扱われています。 このように、DHI の YAML は「どう作るか」ではなく「何が入っていて、誰が動かすか」を宣言しています。そしてここで重要なのは、BuildKit が YAML を直接ビルドしているわけではないという点です。 DHI の Frontend がこの YAML を読み込んで中間表現(LLB)へコンパイルし、あとは通常通り BuildKit がビルドを実行します。つまり、DHI の YAML は「別言語」ではなく、Frontend を差し替えて得た “別の入力形式” なのです。 たとえば不要パッケージの除外ひとつとっても、Dockerfile では apt-get remove → autoremove → キャッシュ削除と手順を重ねる必要があります。一方、DHI なら - '!mawk' の1行で意図が完結します。手順(How)ではなく意図(What)だけが残るため、セキュリティ監査や再現性の面で有利です。DHI が宣言的定義を採用しているのは、こうした相性の良さがあるからです。 忘れられがちな Dockerfile の公式推奨設定 今後、DHI のような宣言的フロントエンドがすぐに主流になるかは未知数であり、当面は既存の Dockerfile 運用が続くでしょう。 しかし、DHI が示す「Frontend は明示し、選ぶものである」という観点は重要です。まずは Docker 公式が推奨する以下の2行を、忘れずに Dockerfile の先頭へ記述しましょう。 # syntax=docker/dockerfile:1 # check=error=true # syntax=... 使用する Frontend を固定し、手元の環境と CI の違いによるビルド結果の揺れを防ぎます。 # check=error=true BuildKit の静的解析(lint)を強め、警告レベルの記述を CI で弾けるようにします。 これらを習慣づけるだけで、「Frontend を明示し、品質を保つ」文化に確実に近づきます。 まとめ DHI から学べる本質は、BuildKit は Frontend を自由に差し替えられるという点にあります。この視点を持つと、DHI は単なるセキュアなベースイメージではなく、ビルド定義の抽象度を一段上げる試みとして見えてきます。 「手順を書く」から「状態を宣言する」への移行は、Infrastructure as Code で何度か見てきた流れと重なって見えます。DHI を触ってみて、その発想がコンテナビルドの入力形式にも持ち込まれていることを実感しました。 将来的にビルドのパラダイムがどう変わるにせよ、まずは見逃されがちな # syntax=... と # check=... をきちんと置くこと。タイミーでも Cloud Run / Vertex AI Pipelines の DHI 移行を進める中で、Frontend 指定の差がビルド結果の揺れに直結する場面に何度か遭遇し、この2行の重要性を改めて感じました。DHI がもたらした視点を持ちつつ、足元の運用を公式のベストプラクティスで堅牢にする。これが、現実的で安全なコンテナ運用の第一歩です。 参考文献 Docker Hardened Images - カタログリポジトリ Debian 13 Base 定義ファイル(13.yaml) — 記事中の YAML 定義例の抽出元 Custom Dockerfile syntax - Docker Docs Build hardened images - Docker Docs We're Hiring! サプライチェーンセキュリティや ML 基盤の足回りに興味を持っていただけたなら、ぜひ一緒に働きませんか。タイミーでは、ML プラットフォームの構築・運用やサプライチェーンセキュリティの強化に取り組むエンジニアを募集しています! 少しでも興味を持っていただけましたら、ぜひ以下のリンクから詳細をご覧ください。 MLOpsエンジニア シニアMLOpsエンジニア 募集ポジション一覧
こんにちは、株式会社タイミーで MLOps エンジニアをしている KY です。普段は ML プラットフォームの構築・運用を担当しています。 私たちのチームでは、機械学習エンジニアやデータサイエンティストが開発に集中できるよう、VS Code のリモート開発(Remote SSH および Dev Container)を活用した開発環境を提供しています。本記事では、その中でも 共通 Dev Container Feature によるガードレール にフォーカスし、各チームが自分たちで開発環境を立ち上げられることを前提にしながら、セキュア・バイ・デフォルトをどう実現しているかをご紹介します。 なぜ Dev Container Feature にガードレールを寄せるのか この記事を書こうと思ったきっかけは、もともと機械学習エンジニアやデータサイエンティスト向けだった開発環境を、データアナリストをはじめとする別職種のメンバーにも広げ始めたことでした。ユーザー層が広がるにつれ、「どこまでを各自の設定に任せ、どこからを仕組みで縛るか」をあらためて考え直す必要が出てきた、というのが出発点です。あわせて、組織として求められるセキュリティレベルも年々高まってきています。 ML プラットフォーム特有の事情として、ユーザーの専門領域が幅広い、という点があります。機械学習エンジニアやデータサイエンティストはモデリングやデータ分析を主戦場としており、依存パッケージの脆弱性管理やコンテナの権限設計といった領域は、本来の業務の中心ではないことが多いです。だからこそ、これらをユーザー個々の習熟度に委ねるのではなく、プラットフォーム側で初期値を配る方針を取りました。各チームがセルフサービスで開発環境を立ち上げられ、特別な設定をしなくても初期状態でセキュリティのベースラインが担保される状態を目指しています。推奨パスに乗るだけで安全に進められる、いわゆる「ゴールデンパス」の発想であり、セキュア・バイ・デフォルトを仕組みで成立させるアプローチです。 この方針を devcontainer.json レベルで素直に表現できる仕組みが Dev Container Feature でした。Feature を1行足すだけで宣言的にガードレールが適用されるため、「各チームが自律的に環境を立ち上げつつ、危険な操作だけは仕組みで塞ぐ」という設計とよく噛み合っています。 共通 Dev Container Feature によるガードレール 私たちの開発環境では、共通化した Dev Container Feature(以下、共通 Feature)を配っています。まず、ベースイメージと Feature の役割は明確に分けています。Docker Hardened Images(以下、DHI)をベースにした開発用イメージでは、各種開発ツール(Python / uv / gcloud / Claude Code など)をインストールしておきます。共通 Feature では、それらツールの設定ファイル配置とガードレール適用のみを担います。 この前提のもと、各チームの devcontainer.json は以下のようにシンプルで、ベースイメージを指定し、共通 Feature を追加するだけで、後述するガードレールがまとめて適用されます。 { "image": "asia-northeast1-docker.pkg.dev/<PROJECT>/<CUSTOM_DHI_PATH>:<TAG>", "features": { "asia-northeast1-docker.pkg.dev/<PROJECT>/<CUSTOM_FEATURE_PATH>:<TAG>": {} } } こうしてレイヤーを分けておくと、ツールの入れ物とポリシーの適用が混ざらずに整理されるため、よりセキュアに締めやすいという体感があります。たとえばポリシー側だけを Renovate で継続的に更新していけるので、イメージの差し替えと独立してセキュリティ設定の追従・レビューを回せます。なお、ベースイメージ側で押さえるべきリスク(OS パッケージの脆弱性など)と、Feature 側で押さえるべきリスク(ツールの権限・設定)をどう切り分けるかといった論点もあります。ただし本記事のスコープ外のため、詳細は割愛します。 この Feature がプロビジョニング時に各種設定ファイルを配置し、ガードレールを自動で効かせます。実際には複数のツール設定を同じ方式で配布していますが、本記事では代表例として AI エージェントの制御を取り上げます。 Claude Code などの AI エージェントの制御 昨今、Claude Code のような AI コーディングエージェントが普及していますが、無制限の権限を与えると破壊的変更や意図しないデータ送信のリスクがあります。共通 Feature は /etc/claude-code/managed-settings.json を自動生成し、システムレベルで制御を行います。 { "strictKnownMarketplaces": [ { "source": "github", "repo": "<ORGANIZATION>/<REPOSITORY>" } ], "allowedMcpServers": [ { "name": "<APPROVED_MCP_NAME>", "command": "..." } ], "permissions": { "deny": [ "Bash(sudo:*)", "Bash(gcloud:*)", "Read(~/.config/**)" ] } } ※ 実際の設定から一部を抜粋しています。 プラグインマーケットプレイスと MCP サーバーは、社内で承認されたもののみに制限しています(ホワイトリスト形式)。また、sudo や gcloud などの権限昇格・クラウド操作、~/.config/ 配下の機密情報へのアクセスといった危険な操作は、Deny リストでブロックしています。ユーザー側の settings.json では上書きできない managed settings として配置しているため、「うっかり緩めてしまう」ことを構造的に防げます。 Feature に寄せることの嬉しさ これらを共通 Feature として提供していることで、以下のようなメリットが得られています。 各チームの devcontainer.json は Feature を1行足すだけでよく、セキュリティ設定の知識なしにベースラインを満たせる。 Feature のバージョンを上げるだけで、全社的にガードレールを一括更新できる(Renovate で自動 PR される)。 設定の出所が Feature に集約されているため、監査やレビューの対象が明確になる。 実際に運用してみると、Renovate の PR を1本マージするだけで全チームの Claude Code 設定が同時に更新されるのは、想像していた以上に運用が軽くなったと感じています。 補足:周辺で効かせている多層防御 共通 Feature だけで全てを押さえようとせず、周辺の仕組みと組み合わせて多層防御を成立させています。ベースイメージには DHI を採用してコンテナ起動時点でのベースラインを引き上げ、ホストとなる Remote SSH 用 VM 側にも同等のポリシーを展開し、依存関係は Dependabot / Renovate で継続的に追従させる、という具合です。 おわりに 今回は、MLOps チームが 共通 Dev Container Feature を使って、ML 開発環境のガードレールをどのように設計・運用しているかをご紹介しました。 振り返ってみると、ツールは DHI イメージ、設定は共通 Feature、更新は Renovate と責務を分けておくと、それぞれに対するレビューや更新のサイクルを独立して回しやすいのが大きな利点でした。ガードレール自体を作ることよりも、ガードレールを錆びさせない構造に落とすことが、各チームの自律性を損なわずにベースラインを引き上げていくうえでの要だったように思います。 参考文献 Claude Code - System settings: /etc/claude-code/managed-settings.json に関する公式ドキュメント Dev Containers - Features: Dev Container Feature の仕様 こうした「セキュア・バイ・デフォルトな ML 開発環境」を、より多くのチームと一緒に磨き込んでいきたいと考えています。 We're Hiring! タイミーでは、ML プラットフォームの構築・運用やセキュアな開発環境の整備に一緒に取り組んでいただけるエンジニアを募集しています! 少しでも興味を持っていただけましたら、ぜひ以下のリンクから詳細をご覧ください。 MLOpsエンジニア シニアMLOpsエンジニア 募集ポジション一覧
1. 自己紹介・経歴 はじめまして、データアナリストのrizumuです。2025年にタイミーに入社しました。 前職ではファッション系のCtoCマーケットプレイスを運営する会社で約4年間データアナリストとして働いていました。UIの分析やクーポン施策の効果検証、顧客セグメントの分析などを担当していました。 2. なぜタイミーを選んだか 転職活動で最も重視したのは、アナリストが多い環境で働きたいという点でした。 前職のチームでは、少人数ならではのスピード感や、幅広い領域を任せてもらえる環境に感謝していました。一方で、「この分析アプローチで良いのか」「他のアナリストはどう考えるのか」と壁打ちをしたい場面では、相談できる相手が限られるもどかしさもありました。分析は一人で完結させようと思えばできてしまう仕事ですが、だからこそ他のアナリストの視点に触れる機会が、自分の成長には欠かせないと感じていました。 一方タイミーは、データを事業の意思決定に活かすことに組織として積極的に投資している姿勢が、選考を通じて伝わってきました。この人数の差は単なる規模の話ではなく、分析の型や議論の文化に触れられる機会が増えることを意味します。ここでならさらにアナリストとしてのスキルを伸ばせると感じたので、タイミーに転職することにしました。 3. 入社して驚いたこと 1つのプロジェクトに複数のアナリストが関わる体制 まず驚いたのは、プロジェクトの体制です。タイミーでは1つのプロジェクトに必ずリードメンバーが一人いて、その上で領域ごとに担当が分かれる形で複数のデータアナリストが関わります。 前職では、基本的に1プロジェクトにつきアナリストは一人、という体制でした。同じチームにアナリストはいても、プロジェクトの深い文脈を理解しているのは担当者だけ。他のメンバーに相談したい場面でも、まずは理解の前提をそろえるために背景共有から始める必要がある場面がありました。 結果として、一人で抱え込んで意思決定する場面が多かったように思います。 タイミーでは、同じプロジェクトに対して最初から共通理解を持った仲間が複数いる。だから「この切り口でいいのか」「この数字の解釈、どう思う?」といった相談を、前提の説明なしにその場で進められます。共通理解を持った相談相手がいる状態は、分析の進めやすさを変えてくれました。 リードメンバーへの相談ハードルの低さ もうひとつ驚いたのが、リードメンバーへの相談のしやすさです。ここでのリードとは、直接の上司ではなく、プロジェクトの中でリードの立ち位置を担うアナリストを指します。Slackで気軽に聞けるのはもちろん、リモート中心の環境なので、「今すぐちょっと相談したい」と思えばGoogle Meetで時間をもらうこともできます。立ち上がり期には、その点に助けられました。 ダッシュボードに求められるクオリティの高さ 想像以上だったのが、ダッシュボードに求められる見やすさ・使いやすさの水準です。データアナリストだけでなく営業など異なる職種の方も使うため、数字が正しいだけでは足りず、誰が見ても意図が伝わり、迷わず使えることが要件になります。ダッシュボード単体で完結する品質が必要、という感覚は業務に入って分かった部分でした。 これらを通して感じるのは、アナリストが多い環境の価値が、日々の相談しやすさやアウトプット基準の高さという形で具体的に現れている、ということです。 4. 半年やってみて、これから 具体的な業務エピソードでいうと、あるプロジェクトで担当したダッシュボード構築の案件が思い浮かびます。ステークホルダーが使い道の想いは持っているものの、ダッシュボードとして何を見るべきかの要件は固まっていない状態からのスタートでした。まず叩き台を作り、リードのデータアナリストからフィードバックをもらいながら要件を詰めていき、最終的には当初の目的に沿った形に仕上がったと評価をいただけました。 このプロジェクトに限らず、目的を起点に形を組み立てていく仕事を経験する中で、半年で一番変わったと感じるのは、以前より目的を強く意識するようになったことです。事業部の業務を十分に理解できていない状態から関わることが多く、目的を掴めていないとアウトプットはすぐにブレてしまう。解像度高く目的を持ち続けることの優先度が、自分の中で上がりました。加えて、自分一人では思いつかない分析の切り口や議論の進め方に日々触れられるのは、データアナリストが多い組織ならではだと実感しています。 今後チャレンジしていきたいのは、AI活用の幅を広げることです。SQL生成などは日常的に使っていますが、最近特に手応えがあるのはダッシュボードのモック作成です。自作のClaudeスキルを使うことでイメージに近いモックが最初から出てきます。一方で実装工程はまだ手作業が中心なので、ここをもっと簡単に進められる仕組みを作っていけたらと感じています。 AI活用の面白さは、個人の業務が速くなるだけにとどまりません。データアナリストが多い組織とAIへの意識の高さが重なると、一人のスキルや得意領域を他のメンバーも扱えるように広げていけます。自分が扱えるスキルやチャレンジできる領域も自然と広がっていく、この循環こそ、この半年で感じているタイミーで働くことの面白さだと思っています。 もし、かつての自分と同じように小規模なデータアナリスト組織で働いていて、次のステージを考えている方や、AIを活用しながらデータアナリストとしての幅を広げていきたいと考えている方がいれば、この記事が何かのきっかけになれば嬉しいです。 We're Hiring! タイミーでは、ともに働くメンバーを募集しています! データアナリストのポジションも募集中です。カジュアル面談も行っていますので、少しでも興味がありましたら、お気軽にご連絡ください。 https://product-recruit.timee.co.jp/
こんにちは。昨年度まで社会人大学院生(修士課程)として学び、無事卒業した Hunachi です 🙌 研究生活の中で、SICS 2026 と DEIM 2026 に参加し、論文の執筆や発表、ポスター発表をしてきました。 私の研究内容は「Android搭載端末での pKVM 環境を使ったセキュアな声紋認証の実装と評価」です 👀 このブログでは、 私が研究で扱っている pKVM ってなに? どんな研究をしていたのか(ざっくり) 学会に参加したり、論文を書いて発表してみての感想 社会人大学院生をしてみた感想 以上の4 本立てで、私の研究や大学院生活について紹介していきます。 SCISは函館開催でした。その時に食べたごっこ汁 🐟 pKVM ってなに? モバイル端末でも「セキュアな実行環境」が欲しい 最近のスマートフォンでは、生体認証・決済・オンデバイス AI(Gemini Nano など)と、機密性の高い処理を端末上で動かす場面がどんどん増えていますよね。 Android でのセキュアな環境としては 2014 年から Trusty TEE(Trusted Execution Environment)という ARM TrustZone ベースの隔離環境が使われてきました。Android の一般的なアプリが動作する環境(REE: Rich Execution Environment)とは、ハードウェアレベルで分離されたセキュアな環境です。そのため、堅牢なセキュリティを実現できます。 ただし TEE には以下の弱点があります。 利用できるメモリが数 MB 程度ととても小さい 開発のハードルがそれなりに高い 端末のベンダーによってセキュリティの質がまちまち 特に利用できるメモリが少ないので、DNN モデルなどを動かすのは大変困難です 😖 pKVM の登場 そこで Android 13 から導入された Android Virtualization Framework(AVF) の中核として、pKVM(Protected KVM) という仮想化技術が組み込まれました。 ざっくり言うと、 ベースは Linux 由来の KVM(Kernel-based Virtual Machine) そこに「ホスト OS からも触れない VM(Protected VM, pVM)」という概念を載せる 端末の物理メモリ容量いっぱいまで使える隔離環境が手に入る という、Trusty TEE のメモリ制約を解消した比較的新しい技術です 🚀 ちなみに数年前、「Pixel で root を取らずに Linux(Arch や Ubuntu)が動かせる」という話題、目にした方もいるんじゃないでしょうか。Danny Lin 氏の Nestbox というアプリで Android 上に Linux VM を立ち上げるものです(参考記事)。この基盤になっているのがまさに pKVM で、「ホスト OS から保護された VM」という枠組みを使えば、セキュリティ用途だけでなく汎用的な OS だってホストできてしまう、というのを実証した一例です。 pKVM のアーキテクチャをざっくり ARM のアーキテクチャでは、特権レベルが Exception Level(EL) という階層で分かれています。pKVM 環境に関する階層分けはこのようになっています。 EL2: pKVM ハイパーバイザ EL1: Android Host OS と Protected VM EL0: ユーザアプリケーション EL2 で動く pKVM がステージ 2 ページテーブルを使って、ホスト OS からの pVM メモリへのアクセスを物理的に遮断します。さらに IOMMU を使うことで、DMA デバイス経由の不正アクセスもブロックしてくれます。 また、pKVM上で動かすプログラムはC/C++で書く必要がありますが、TEE向けアプリの開発に比べれば容易です。 セキュアな環境を成り立たせる仕組み pKVM(AVF)の凄いところは、ただメモリを隔離するだけじゃない点です。 pvmfw(Protected VM Firmware)がペイロードの署名を検証して改ざん検知 DICE(Device Identifier Composition Engine)プロトコルで pVM ごとのシークレットを導出 DICEで導出したシークレットからsealing secretを生成し、さらにsealing keyを作成して永続データなどを暗号化 pVM 終了時にはハイパーバイザがメモリページをゼロクリアして残留防止 つまり、コードの正当性 → 起動時のシークレット → 永続データ → 終了時の残留防止 まで一貫してハイパーバイザがケアしてくれる、という設計です。 そして 2025 年 8 月、Google が pKVM で SESIP Level 5 認証を取得したと発表しました 🎉 SESIP(Security Evaluation Standard for IoT Platforms)は IoT デバイス向けセキュリティ評価基準で、Level 5 は最高レベルです。大規模消費者向けに展開されるソフトウェアセキュリティシステムとして取得したのは世界初で、最新かつかなりセキュアな技術であることがわかります(Google Online Security Blog)。 私の研究をざっくり やったこと ここからは自分の研究をかなりざっくり紹介します。 タイトルは「Google Tensor 搭載端末の pKVM におけるセキュアな音声処理および声紋認証の実装手法と課題の検討」です。 論文はこちらから読めます 👉 DEIM2026 3D-01 すごく簡単に言うと、 (pKVM環境)上で話者識別のDNNモデルを動かし、実用可能な処理速度で動作する声紋認証システムアプリを実現 pKVM のメモリアクセス特性を細かく測定 提案システムの認証精度・処理時間・pKVMのVM 起動時間などを多角的に評価 を行った論文です。 そしてありがたいことに、この発表で DEIM 2026 学生プレゼンテーション賞 をいただきました 🎉 一緒に研究を進めてくれた共著の先生方、コメントをくださった皆さん、本当にありがとうございました 🙇 まだまだ改善の余地がたくさんある研究内容ですが、興味のある方は論文を読んでもらえると嬉しいです 🙇 学会の感想 SICS に参加した感想 SICSは、以前は暗号系の発表が多かったようですが、最近は傾向が変わってきたようです。セキュリティ関連の発表では、高レイヤの話も多く見られました。特にLLMのセキュリティや研究方法に関する講演や発表が印象的でした。最先端のLLMの研究をしている日本人研究者もいることや、LLMのセキュリティの研究がどこまで進んでいるかの話を聞くことができ、面白かったです。 DEIM に参加した感想 たくさんの学生さんが参加している学会で、色々な研究の発表やポスター発表を見ることができました。特に土日にリモート開催だったので、社会人の私にとって大変嬉しかったです。LINEヤフーさんのDBの話なども興味深く聞かせていただきました。 最近の研究は、やはりLLM関連が多く、自分も研究でLLMも扱えるよう、ある程度は詳しくならないといけないと思いました。 論文執筆・発表・ポスター発表をしてみた感想 学部時代の研究をそのまま続けなかったこともあり、成果が出せる研究テーマにたどり着くまで時間がかかり、とても大変でした。一方で、先生方の助言やAIの活用により、先行研究や最新技術の調査を効率化できました。その結果、成果を出せてよかったです。 また論文を執筆するにあたり、慣れない部分については、AIに手助けしてもらいながら執筆しました。4年前の学部時代や高専時代に論文を書いた時と比べて、LaTeXのエラーに悩まされる時間や、誤字脱字の修正にかかる時間が、ほぼゼロになりました。本当に楽な時代になったなと感じます。 発表では厳しめの質問をいただくこともありましたが、それ以上に嬉しいこともありました。似た研究をしている方が少ないにもかかわらず、特にDEIMでは私の研究に興味を持って質問してくださる方が多く、とても嬉しかったです。 人に自分の研究内容を伝えることは、社会人におけるプレゼンテーションを行う際にも活かせるなと思いました。 社会人大学院生(修士課程)をしてみた感想 大学の教授やD進している同期、夫の家事サポートがあったからこそ、卒業できました。関係者の皆さんに感謝しかありません。 人におすすめできるかというと、とても忙しい生活スタイルになるため、研究が趣味な人以外にはおすすめしにくいです。ただ、AIの活用で調査や文章執筆が容易になった今の時代だからこそ、「チャレンジは可能だ」と思います。 私の感じたメリット・デメリット メリットは、金銭的な問題で困りにくいことです。いろいろな理由があり、猫と暮らしている自分には働かないという選択肢がなかったため、社会人学生を選びました。働きつつ学生でいることを許してくれた大学の教授には感謝しかありません。そのおかげで猫と暮らしつつ学費も安定して払うことができました。 デメリットは以下のとおりです。 大学以外のことをするプライベートな時間がかなり少なくなること 研究に時間を費やす必要があるのはもちろんのこと、学会や授業の参加で有給が消費されます 仕事や大学が忙しい時期には睡眠時間以外はパソコンの前にいる、というような不健康な生活が日常になること 学生らしい生活ができないこと 私の場合は、大学に行く時間が取れず在宅で研究を行なっていた関係で、友人と研究室でおしゃべりしたり、飲み会や合宿への参加などはできませんでした。 また私は、学部時代に大学院の授業単位を取得できる制度を活用していたため、大きな問題はありませんでした。ただし、大学や単位の取得状況によっては、授業のために有給を使う必要が出てくるかもしれません。さらに、大学生らしい生活が送れないのはもったいないと感じるため、個人的には可能であれば通常の大学院生として通うほうがよいと思います。 ※ 私の大学生活のほとんどはコロナでオンラインだった関係で大学生活をまともにしたことがないので意見が偏っている可能性もあります。 ただ、事情があり社会人になる必要がある人やすでに社会人の方で、研究をしたい・続けたい人は十分頑張ってみる価値があると思うので応援しています 🚩 おわりに 引き続きpKVMや研究関連の勉強は続けようと思っています 🧑🎓 最後まで読んでくださってありがとうございました!
こんにちは。タイミーのデータエンジニアリング部 DSグループでMLOpsを担当しているYukitomoです。 私たちのチームでは多くのPythonアプリをモノレポで管理していますが、Dependabotによる依存関係更新PRが多すぎることが運用課題でした。本記事では、Renovateへの移行によって「更新PRの粒度と数をコントロールできる運用」を実現するまでの設計判断と、Python + uv環境特有の注意点を共有します。 この記事の想定読者 Pythonのモノレポ環境で、複数のアプリケーションやライブラリを運用している方 Dependabotが生成する大量の更新PRの対応に疲弊しており、運用を効率化したい方 Renovateへの移行を検討している、または導入したが設定(packageRules)のベストプラクティスに悩んでいる方 パッケージマネージャーに uv を採用している(または検討している)方 要約(TL;DR:この記事でわかること) 本記事では、Python + uv環境でRenovateを運用する際の課題とその解決策(新しすぎるパッケージの除外設定、Google Cloud WIFにおけるブランチ名の文字数制限の回避など)を整理し、実践的なrenovate.json5の設定ノウハウを解説します。 背景 近年はサプライチェーン攻撃が現実的なリスクになっており、Trivyの侵害以降も Python モジュールや JS ライブラリを狙った攻撃が継続して観測されています。PyPI など外部エコシステムに依存する以上、これまで以上に「依存関係をどう安全に運用するか」を真面目に考える必要があります。 一方で、依存関係を「安全に」保つには、継続的にアップデートを回し続ける必要があります。ここで次の課題になるのが、運用対象が増えたときに更新対応のコストがスケールしてしまう点です。 私たちもDependabot運用の効率化を進めてきましたが*1、アプリごとにパッケージ管理へ移行した結果、モノレポ内のpyproject.tomlが増えました。2026年5月時点では、DSグループだけでも約70のPythonアプリケーション/ライブラリを扱っています。Dependabotは脆弱性の検知とPR作成を行ってくれる一方で、依存関係ごとにPRが分割されます。そのため、対象が増えるほど対応コストが急増します。 そこでこの課題を解決するため、Renovateを導入し「更新をまとめて扱える運用」へ切り替える方針にしました。本記事では、公式ドキュメントや公開されている設定例を参考にしつつ、私たちが重視した設定ポイントを整理します。 この記事の前提 言語: Python 依存関係ファイル: pyproject.toml / uv.lock 動作環境: GitHub & Google Cloud 目的: Renovateで「脆弱性対応」と「定常アップデート」を破綻なく回す(PRの数と粒度をコントロールする) 設定ファイル(.renovaterc.json5) 設計方針 私たちが設定で重視したのは以下の3点です。 PRの粒度をコントロールする — patch / minor / vulnerability を適切にグルーピングし、PRの本数を削減する サプライチェーンリスクを軽減する — 公開直後のバージョンを即座に採用しない 小さく始める — まず許可リスト方式で必要な更新だけを有効化し、段階的に広げる 全体像 以下が設定ファイルの抜粋です(各設定の詳細は後述)。 // .renovaterc.json5 より一部抜粋 { extends: ["config:best-practices"], minimumReleaseAge: "N days", lockFileMaintenance: { enabled: true, branchTopic: "lfm", // GCP WIF 127-byte limitに対応するためブランチ名を省略 minimumReleaseAgeBehaviour: "timestamp-optional" // 一時的な対応 }, vulnerabilityAlerts: { groupName: "maintenance", groupSlug: "maint", minimumReleaseAge: "14 days", }, packageRules: [ // packageFileDirをブランチ名に含めつつGCP WIF 127-byte limitに対応するためブランチ名を省略 { matchFileNames: ["base_containers/base/**"], additionalBranchPrefix: "{{{replace 'base_containers/base/' 'b_b/' packageFileDir}}}/", }, // packageRuleを一旦無効化 { matchPackageNames: ["**"], enabled: false }, // グルーピング ---------------------------------------------------- // ルール 1: { matchUpdateTypes: ["patch"], enabled: true, groupName: "maintenance", groupSlug: "maint", }, // ルール 2: { matchUpdateTypes: ["minor"], matchJsonata: ["isVulnerabilityAlert = false"] enabled: true, groupName: "minor updates", groupSlug: "minor", dependencyDashboardApproval: true }, // ルール 3: { matchPackageNames: ["**"], matchJsonata: ["isVulnerabilityAlert = true"] enabled: true, // この2つは vulnerabilityAlerts で設定した値で上書きされます groupName: "maintenance", groupSlug: "maint", }, // マイナーレベルでの破壊的な更新の抑制 ただし脆弱性対応を除く { matchJsonata: ["isBreaking = true and not(isVulnerabilityAlert)"], enabled: false, }, ], // バージョンの更新 bumpVersions: [ { bumpType: "patch", filePatterns: ["{{packageFileDir}}/pyproject.toml"], matchStrings: ["version\\s*=\\s*\"(?<version>[^\"]+)\""] }, { bumpType: "patch", filePatterns: ["{{packageFileDir}}/uv.lock"], matchStrings: ["name = \"[^\"]+\"\\nversion = \"(?<version>[^\"]+)\"\\nsource = \\{ (?:editable|virtual) = \"\\.\" \\}"] } ] } 設定項目の説明 <h3 id="configbest-practices-を土台にす
はじめに こんにちは、タイミーでエンジニアをしている徳富(@yannkazu1)です。 クラウドネイティブ会議2026で発表された「ペアーズ本番環境でのcgroup-aware化との死闘録」がめちゃくちゃ面白かったので、自分の手でも体感したくなりました。 GoのGOMAXPROCSがコンテナのCPU制限を無視するって、実際に見るとどうなるのか? 過剰並列のスループット低下って、数字で見るとどのくらいインパクトがあるのか? スロットリングとスレッド数の関係を自分の目でたしかめたい! 自分で動かして数字を見ないと腑に落ちないタイプなので、ローカルのMac環境で全部再現してみました。 発表の要約 ペアーズのバックエンド pairs-main はGo製でAmazon EKS上で稼働。48コアのNodeで limits.cpu: 5000m(5コア)のPodが動いていたが、GoのGOMAXPROCSがデフォルトで48(=Node全体のコア数)になっていた。これにより以下の問題が発生: 過剰並列: 5コアしか使えないのに48スレッドが走る → Goスケジューラのオーバーヘッド増大 CPUスロットリング: cgroupのクォータ(CPU時間の上限)をスレッドが共食い → 全スレッドが同時に停止 監視の死角: CPU使用率は正常に見えるが、実際はスロットリングで断続的に停止 同じ問題がHAProxy(nbthread=48、CPU制限1コア)でも発生していた。 これらをcgroup-awareな設定(GOMAXPROCS=5, nbthread=1)に修正したところ、大幅に改善した、という話でした。 用語の整理 ここから先で出てくる「コア」「GOMAXPROCS」「クォータ」「スロットリング」あたりがピンと来なくても大丈夫です。記事全体で繰り返し登場するので、最初にざっくり整理しておきます(すでに馴染みがある方はスキップでOK)。 CPUコア・プロセス・スレッド 用語 ざっくりした意味 CPUコア 計算を実行する物理的な実体。1コア = 同時に1つの処理を進められる プロセス 動いているプログラム1つ分の単位 スレッド プロセス内で実際にCPUに割り当てられる作業の単位。1プロセスは複数スレッドを持てる ざっくり言うと、コアの数 = 同時に進められるスレッドの数の上限です。8コアのCPUなら、ある一瞬に進行できるのは最大8スレッドまで。それ以上のスレッドを立ち上げた場合は、OSが順番にコアを割り当て直しながら回します(= コンテキストスイッチ)。 コンテナと cgroup 用語 ざっくりした意味 コンテナ 同じサーバー上で複数のアプリを互いに干渉しないように動かす仕組み(Docker や Kubernetes の中身)。実体はホストのカーネルをそのまま使う 「namespaces で見える範囲を、cgroup で使える量を制限したプロセス(群)」 にすぎず、VM のように専用カーネルを持つわけではない cgroup(Control Groups) Linuxカーネルの機能で「このプロセス群はCPUをここまで・メモリはここまで」と上限を設定する仕組み CPU制限 「このコンテナはCPU 1コア分まで」のような上限設定。実体は cgroup の cpu.max ファイル コンテナの「CPU 0.5コアまで」という設定は、Linuxカーネルが cgroup を通じて「100msのうち50msまでしかCPUを使わせない」という形で強制します。この 100msの枠を「ピリオド」、その中で使ってよい時間量を「クォータ」 と呼びます(cpu.max: 50000 100000 なら「100msのうち50ms使える = 0.5コア相当」)。 CFS スケジューラ Linux のデフォルトの CPU スケジューラを CFS(Completely Fair Scheduler) と呼びます。先ほどの「ピリオド」「クォータ」は、CFS が持つ 帯域制御(Bandwidth Controller) という機能の用語で、cgroup の cpu.max の値を実際にスレッドへ適用する(=クォータを使い切ったら停止させる)のはこの CFS の仕事です。 つまり「cgroup が制限値を持ち、CFS がそれを実施する」という分担関係。後の実験で出てくる nr_periods(CFS が時間を区切る単位の総数)や nr_throttled(CFS が停止させたピリオドの数)も、この CFS 帯域制御の統計を見ています。 Goroutine と GOMAXPROCS(Go特有の話) 用語 ざっくりした意味 goroutine Goの軽量スレッド。OSスレッドより遥かに軽く、1プロセスで数万〜数百万個立ち上げられる OSスレッド OSが実際にCPUにスケジュールするスレッド。コアを取り合うのはこちら GOMAXPROCS Goランタイムが同時に走らせるOSスレッドの数の上限。デフォルトはホストのCPUコア数 goroutine を何万個立ち上げても、Goランタイムは GOMAXPROCS 個の OSスレッドの上にそれらを多重化して実行します。つまり同時に CPU を握っているのは最大でも GOMAXPROCS 個。この割り当てを管理するのが Goスケジューラ です。 ポイントは、コンテナのCPU制限が下がってもデフォルトの GOMAXPROCS はホストのCPU数のままということ。これがそもそも今回のテーマで、後の実験でその挙動を実際に確かめます。 過剰並列 CPU 制限よりも多くのスレッド(や goroutine、ワーカー)を同時に走らせている状態を指します。たとえば 5 コア相当の CPU 制限に対して GOMAXPROCS=48 なら、約 9.6 倍の過剰並列。実際に走れるのは制限分のスレッドだけなので、残りはスケジューラの上で順番待ちをしつつ、共有クォータを早食いし合うことになります。 Go の GOMAXPROCS に限った話ではなく、HAProxy の nbthread、Nginx の worker_processes、Puma の workers など、「並列数のデフォルトがホスト CPU 数に依存する」設定はすべて同じ構造で過剰並列を起こします。 CPUスロットリング cgroupでCPU 0.5コア分に制限されたコンテナが、たくさんのスレッドでCPUを一気に使おうとすると、Linuxカーネルが 「クォータを使い切ったので、次のピリオドまで全スレッド一時停止」 と強制的にブロックします。これが CPUスロットリングです。 スロットリングが頻発すると、レスポンスが断続的に止まったり、スループットが落ちたりします。その結果、「なぜか遅延がスパイクする」原因になっているケースが多いです。発生状況は /sys/fs/cgroup/cpu.stat に出力されており、本記事では以下の3指標を追います: nr_periods: スケジューラの計測単位(ピリオド = 100ms)の総数 nr_throttled: そのうちスロットリングが起きたピリオドの数(回数) throttled_usec: スロットリングで実際にCPUが止められた累積時間(マイクロ秒) 「回数」だけでなく「累積停止時間」も見るのが重要だ、というのが発表の山場の一つで、後の実験3でその違いがハッキリ出ます。 Thundering Herd スロットリングで停止していた全スレッドが、次のピリオドのリセットで一斉に走り出し、また一瞬でクォータを食い潰して同時に止まる、というサイクルが繰り返される状態を 「Thundering Herd(雷鳴の群れ)」 と呼びます。元はソケット accept など I/O 文脈の用語ですが、cgroup の帯域制御下でも同じ構造の問題が起きます。スレッド数が多いほど被害が大きくなるのは、ここに端を発しています。実験4でその挙動を観察します。 cgroup-aware プログラムやライブラリが cgroup の制限(cpu.max など)を自分で読み取り、その値に合わせて並列度を調整する 設計のことを 「cgroup-aware」 と呼びます。Go 1.25 以降のランタイムや uber-go/automaxprocs は cgroup-aware に GOMAXPROCS を設定します。逆に Go 1.24 以前のように cgroup を見ずにホストの CPU 数だけ見る挙動は「cgroup-aware ではない」状態で、今回の過剰並列はそこから生まれています。 この記事で検証すること # 検証テーマ 発表でのポイント 1 GOMAXPROCSのデフォルト値 コンテナのCPU Limitを無視してホストのCPU数になる 2 過剰並列のパフォーマンス影響 GOMAXPROCSが大きすぎるとスループットが低下する 3 CPUスロットリングの発生 スレッド数が多いほどクォータを早く消費し、停止時間が増える 4 スレッド数とスロットリングの相関 スレッド数に比例してthrottled_usecが増加する 1. ローカル環境構築(Mac) 前提条件 macOS(Apple Silicon / Intel 両対応) Docker Desktopがインストール済み なぜDockerで検証できるのか cgroup(Control Groups)はLinuxカーネルの機能で、macOS 自体には存在しません。しかし Docker Desktop は内部で Linux VM を動かしており、コンテナはその Linux 上で動作します。 ┌─────────────────────────────────────────────┐ │ macOS │ │ ┌────────────────────────────────────────┐ │ │ │ Docker Desktop (Linux VM) │ │ │ │ ┌──────────────────────────────────┐ │ │ │ │ │ コンテナ │ │ │ │ │ │ /sys/fs/cgroup/cpu.max ← ここ! │ │ │ │ │ │ /sys/fs/cgroup/cpu.stat │ │ │ │ │ └──────────────────────────────────┘ │ │ │ └────────────────────────────────────────┘ │ └─────────────────────────────────────────────┘ Docker の --cpus フラグは Kubernetes の limits.cpu と同じく cgroup の cpu.max に変換されます。つまり Kubernetes と同じ仕組みをローカルで再現できます。 Docker Kubernetes cgroup v2 --cpus=0.5 limits.cpu: 500m cpu.max: 50000 100000 --cpus=1.0 limits.cpu: 1000m cpu.max: 100000 100000 --cpus=5.0 limits.cpu: 5000m cpu.max: 500000 100000 セットアップ手順 Step 1: Docker Desktop のインストール Docker Desktop for Mac からインストール。 docker --version # Docker version 27.x.x, build xxxxxxx Step 2: 検証用 Go アプリケーション 本記事の検証コードは以下のリポジトリにまとめています: hirosi1900day/cgroup-throttling-lab git clone https://github.com/hirosi1900day/cgroup-throttling-lab.git cd cgroup-throttling-lab 3つのモードを持つGoアプリケーションを書きました。 モード 用途 info GOMAXPROCSの値とcgroupの設定を表示 benchmark CPU負荷をかけてスループットを計測 throttle-demo CPU負荷をかけてスロットリングの Before/After を表示 コード解説 各パートを順に見ていきます。 1. CPU負荷を発生させる関数 // cpuIntensiveWork はCPU負荷をかける計算処理 // 平方根と三角関数を1万回ループし、意図的にCPUを使い切る func cpuIntensiveWork() float64 { result := 0.0 for i := 0; i < 10000; i++ { result += math.Sqrt(float64(i)) * math.Sin(float64(i)) } return result } この関数が実験の要です。math.Sqrt と math.Sin の計算を1万回繰り返すことで、純粋なCPU負荷を発生させます。I/O待ちが一切ないので、GOMAXPROCS(=ワーカースレッド数)の影響がダイレクトに現れます。 <st
株式会社タイミーでモバイルエンジニア (Android / iOS) をしている、みかみです。介護領域のグロース施策を中心に、AB テストや分析、マーケティングとの連携などにも取り組んでいます。 2026年4月16日に開催された RevenueCat App Growth Annual Tokyo 2026 (以下 RAGA) に参加してきました。 アプリ成長、サブスクリプション、AI をテーマにしたセッションの中から、個人的に印象に残った話をいくつか紹介します。 RAGA について RAGA (RevenueCat App Growth Annual) は、RevenueCat が主催する「モバイルアプリ成長」をテーマにしたグローバルカンファレンスです。RevenueCat は、モバイルアプリのサブスク収益化プラットフォームを提供している会社です。 カンファレンスでは「AI・サブスクリプション・アプリ成長」をテーマに、プロダクト戦略やユーザー獲得、マネタイゼーション設計といったトピックが扱われていました。登壇者は Notion、ElevenLabs、Speak、YAMAP、SmartNews、Mirrativ、NOT A HOTEL といった国内外のアプリ企業の実践者で、経営層・CPO・CTO クラスが多かったのが特徴的でした。加えて RevenueCat Co-founder / CTO による基調講演もありました。 参加した目的 RAGA に参加したのは、アプリグロースに取り組む他社の現場の話を直接聞ける機会だったからです。日々の業務では、アプリの機能開発だけでなく、AB テスト・分析・マーケ連携にも取り組んでいます。エンジニアリングの先にあるグロース領域への関心も、最近広がってきていました。RAGA で扱われるトピックは、まさに自分の関心と重なる内容でした。 もうひとつ、AI に聞けばなんでも答えてくれる時代だからこそ、現場で一次情報に触れる機会を大事にしたいという考えもありました。後からまとめ記事や録画で追える情報も多いですが、一日を通して様々な実践者の話を続けて聞ける経験は、その場に行かないと得られないと思ったからです。 印象に残ったセッション RAGA は2トラック構成で、世界でアプリを成長させたリーダーが集う「Global Track」と、日本市場の実践者や世界進出を目指す起業家が登壇する「Japan Track」がありました。自分が参加した中で特に印象に残ったセッションを紹介します。 1. 原点回帰:iモードから現代のアプリ経済へ RevenueCat 共同創業者兼 CTO の Miguel Carranza さんによる基調講演では、日本のモバイル市場の歴史を起点に、現代のアプリ経済が直面する変化が語られました。基調講演の内容や RAGA Tokyo 全体の様子は ProductZine の詳細レポート に詳しいので、ここでは個人的に印象に残った点を中心に紹介します。 冒頭で印象的だったのは、現代のアプリ経済で当たり前になっている概念の多くが日本発だった、という視点です。1999 年の i-mode、絵文字、LINE など、日本のモバイル文化が今のアプリ経済につながっているという話から始まりました。 同時に、日本市場の大きさも具体的な数字で示されました。 日本は世界 3 位のアプリ市場 ユーザー一人あたりの年間支出は $166 2027 年にはスマホユーザーが人口の 94% に達する見込み 一方で、印象に残ったのは「市場が大きい」という話だけではありません。AI によってアプリを作るハードルが下がった結果、過去 4 年間で アプリの供給は7 倍に増え、市場には明確な分断が起きているそうです。上位 25% のアプリは収益を 80% 以上伸ばす一方で、下位 25% は 33% 減少しているという話もありました。 この話を聞いて、アプリ市場は「作れば伸びる」市場ではなくなってきているのだと感じました。AI によって作る力が広がるほど、作れること自体の価値は相対的に下がり、継続して使われる体験をどれだけ設計できるかがより重要になっていくのだと思います。 最後に取り上げられていた 「AI パラドックス」 も、その流れとつながる話でした。AI を組み込んだアプリは初期コンバージョンが強い一方で、解約が約 30% 早く、継続率に課題を抱えるケースが多いそうです。AI の新しさで一度使ってもらうことはできても、継続的な価値に落とし込めなければ LTV にはつながらない、という指摘として受け取りました。 アプリ市場というと、これまで漠然と「大きそうだな」くらいに捉えていましたが、今回の話を聞いて、規模の大きさ以上に競争の中身が変わってきていることを実感しました。ペイウォール設計やトライアル期間、継続率改善といった細部への投資が差を生むという話は、日々のグロース施策を考えるうえでもかなり示唆的でした。 2. 広告視点で考えるサブスクハックネタお披露目会 Repro の中野竜太郎さんと Alethne の坂本翔也さんが、Adjust の高橋将平さんのモデレートで議論したパネルディスカッションです。広告運用・計測・クリエイティブ最適化など、アプリ成長を広告の視点から見つめてきた登壇者ならではの、現場感の強い話が詰まったセッションでした。 冒頭で出てきたフレーズが強烈です。 "CPI (Cost per install) だけ見る投資はナンセンス。" "エンゲージメントの時代じゃない、アクティベーションの時代だ。" 登壇者たちが共通して強調していたのは、広告で獲得したユーザーの8割は Day 0 で離脱するという前提です。離脱を防ぐ鍵になるのが 「アハ体験」、つまりユーザーがアプリの価値を実感する瞬間の設計です。リワードで引っ張ってくるのではなく、自社サービスのコア体験そのものをゲーム化していくのが大事だ、という主張でした。 もう一つ参考になったのが「マジックナンバー」と最適化トリガーの設計の話です。トライアル開始を成果イベントにするのは弱く、「7日間トライアルで辞める気のユーザーは2時間で消える」というデータがあるそうです。そこで、「2時間以上滞在したユーザー」や「特定アクションを N 回実行したユーザー」をマジックナンバーに設定したほうが、広告の最適化トリガーとしても成果が出やすいとのことでした。 AB テストや分析に取り組んでいる身として、「何をイベントとして計測するか」の解像度を一段上げるヒントになる話でした。単に画面遷移を計測するのではなく、ユーザーがそのアプリの価値を実感したシグナルとしてイベントを設計する、という視点が新鮮でした。 3. 激動の時代、日本発メガベンチャーはどのように世界で勝ちに行くのか SmartNews のホン・ランドンさんと Mirrativ の赤川隼一さんによるパネルディスカッションです。コミスマの坂本達夫さんがモデレーターを務めたこの回が、自分にとっては強く印象に残ったセッションでした。プロダクト・グロース・経営の観点から、AI の進化と激化するグローバル市場にどう立ち向かうかが議論されました。 特に印象に残ったのが、グローバル展開の戦略の話です。展開する国の数によって取るべき戦略は変わるそうです。1 カ国に絞るなら徹底した現地化が有効、多国展開なら同一プロダクトを広げて手応えのある市場に集中投資する、という対比でした。いずれにせよ、個別市場の局所最適ではなく、会社全体の収益最大化を基準に手段を選ぶべきだ、という話が腑に落ちました。 セッションの締めくくり、ランドンさんからの「AI 時代に変わるもの・変わらないものは?」という問いに対する赤川さんの答えが、一日で最も刺さった言葉でした。 "変わるもの = ほぼ全部。アンラーニングとスピードが勝負。変わらないもの = 現地現物。" 「優秀な PM は必ず現地でユーザーが迷う姿を観察する」という話でした。AI で機能開発のスピードが上がる時代だからこそ、ただ機能開発を進めるだけではなく、問いを立てる力や、現場やユーザーに直接聞きにいくことの重要性は、むしろ増しているように感じます。 おわりに 参加してみて改めて感じたのは、AI 時代だからといって仕事が華やかになっているわけではない、ということでした。 各セッションで語られていたのは、AI を使いこなす派手な事例というよりも、その手前にある地道な計測や粘り強い観察、ユーザーの一次の声を拾い続ける姿勢だったと感じます。今回語られていた事例のどれもが、こうした地道さの積み重ねの上にあるということを、当たり前のようでいて改めて強く感じました。 AI でプロダクトの作り方は変わっていきますが、アプリを成長させるために向き合う対象は変わらず、むしろ AI が広がるほど、ユーザーをどれだけ深く読めるかがアプリの差として出やすくなっていくのかもしれない、と感じた一日でした。 カンファレンス後のアフターパーティーも独特でした。ライブや DJ セットを交えた構成で、日中のセッション合間にもスタンダップコメディが入るなど、国内の他のカンファレンスと比べても振り切り方が際立っていて、一日を通して印象的でした。
はじめに 株式会社タイミーでデータアナリストをしている平野です。タイミーキャリアプラス(以下、タイキャリ)という新規事業に、リードDAとして半年あまり伴走してきました。 タイキャリは、タイミーのスキマバイトのデータを起点に、長期就業(正社員採用)を支援するサービスです。タイミーで得た就業実績・バッジを"職務経歴書"として活用できるのが特徴で、2024年2月に開始されています。 新規事業DAの面白さ 0→1のフェーズで、データと事業を一緒に育てていく感覚を味わえる仕事です。 自分の分析が事業の意思決定に直結する瞬間が日常的にある 事業責任者・GM・PdMと机を並べて、事業の方向づけにデータで参加できる データ基盤・モニタリング・分析テーマをゼロから設計できる この記事で書くこと 一方で、新規事業ならではの難しさもあり、半年の間に"知っていれば避けられた"失敗を数多く経験しました。同時に再現可能な"型"が存在するとも確信しています。 本記事では、私が踏んだ落とし穴とそこから抽出したアクションを時系列で整理します。これから新規事業に入るDAの参考になれば嬉しいです。 Part 1: 新規事業DA特有の3つの難しさ 💡 難しさはPart 2の予防アクション、Part 3の原則とセットで読むと"克服可能な型"として見えてきます。 私が実際に踏んだ落とし穴を3つ共有します。どれも新規事業DAが共通して直面しうる構造的な問題で、「誰かが悪い」ではなく、立ち上げ期に起きやすい"あるある"です。DA側がどう動くと摩擦や手戻りを減らせるか、という観点で整理します。 ① 統制構造の有無で難易度が桁違いに変わる DAへの依頼を集約する"要望窓口"(bizops的人材)がいるかどうかで、伴走の難易度が大きく変わります。立ち上げ初期は役割や導線が固まりきっていないため、集約は"自然発生"しないことも多いです。 集約役がいる事業: 要望が一本化、定義の議論は1対1で済む 窓口体制が立ち上がる前の事業: DA側が複数の現場と直接やり取りし、定義確認を個別に進める必要が出てくる 人材紹介領域はbizops担当の方がいてスムーズだった一方、DR領域では複数の現場と直接やり取りしながら同じ定義の議論を繰り返すことになりました。 ② DA介入前にプロダクト開発が進んでしまう プロダクト駆動型の新規事業では、スピード重視でDAが合流する前に実装が固まることが起きやすく、後から計測設計を整える負担が大きくなります。 DRサービスでは、私が伴走を始めた時点で、計測設計にDA観点を反映する場がない状態でした。一気通貫のファネル分析のため、計測設計の整理を提案するところから始める必要があったのです。 新規事業の速度感を考えれば自然なこと。だからこそDA側から早期に合流する関係性を作りに行くことが重要だと痛感しました。 ③ DA側が組織横断の優先順位付けの場を提案できていない 立ち上げ期は、各担当者が自分の領域の進捗を重視するのは自然(むしろ健全)です。一方で、全体の優先順位を議論する場は用意されていないことも多く、DA側から立ち上げないと、横断の判断軸を持って動くのが難しくなると感じました。 私も最初の数ヶ月は会議体を提案できず、腰を据えるべきテーマに集中しきれない期間を過ごしました。 Part 2: 時系列アクションリスト 新規事業にDAが入るとき、いつ何をやるべきかを時系列で整理します。各アクションに「なぜそう思ったか」のエピソードを添えました。 🔵 Day 0: アサイン前の意思決定 アクション 内容と効くポイント 🧗 DAをディープダイブ(兼務させない) 新規事業は定義変更・指標追加が高頻度で、半コミットでは事業理解が追いつかない。特にリードアナリストは他案件と兼務させないことが、後の伴走の質を大きく左右する 💡 最初からディープダイブ前提でアサインされたことが、信頼関係構築 → 中長期伴走パートナー化につながりました。 🟢 Week 1-4: 関係性構築・PJ立ち上げ 🎯 特に効いた3つ: 関係者ヒアリング / 要望窓口の確認 / ログ設計レビュー合流(プロダクト駆動型) アクション 内容と効くポイント 📋 関係者ヒアリング 事業責任者・GM・現場メンバーに事業の目的・課題・関心事をひとりひとり丁寧に聞く。この時間投資が後の伴走の土台になるため、急ぎたい気持ちを抑えても話を聴く価値がある 💬 依頼チャンネル合意 Slack・依頼フォーム等を事業側と合意して「どこに・どの形式で依頼を投げるか」を明確化。受け手のオペが回り、依頼の取りこぼしが減る 🔁 週次定例の継続参加 事業の解像度を大きく上げる手段。ただし参加だけでは何も変わらない。「この定例から何のアクションを生むか」を常に自問する姿勢が大事 🚪 要望窓口の確認/提案 集約役不在のままだとPart 1 ①の状況に陥りやすい。いない場合は、GMや事業部のミドルマネージャーに集約役を担ってもらう依頼導線の設計をDA側から提案 🔍 ログ設計レビュー合流 プロダクト仕様検討・ログ設計レビューの場にDAが入れるよう、開発開始前から合流しておく。これを逃すとPart 1 ②の罠にはまる 📚 ナレッジのGit管理 AIコーディングツール(Claude Code・Cursor・Devin等)が参照できる形でナレッジを蓄積。分析の壁打ち・クエリ作成の工数が劇的に削減されるため、アサイン初期の最優先投資 ⚠️ 前任期に「定例参加だけでアクションに繋がらない」時期がありました。参加は手段、目的ではない。 🟡 Month 1-3: 目先の困りごと解決期(信頼残高を貯める) 🎯 特に効いた3つ: 爆速対応+問い返しの両立 / 要件定義を向き合いと一緒に言語化 / 基盤整備のタイミング評価 アクション 内容と効くポイント ⚡ 爆速対応 + 「なぜ/必要性/定義」の問い返し 初動の爆速対応は信頼関係構築の重要戦略。「このDAは価値がある」と認識されると、後のポジション変更が楽になる。ただし依頼対応に留まり続けると"依頼を捌く人"として固定されるため、「なぜやるか/本当に必要か/定義は適切か」を毎回問い返す姿勢を早期から取り入れる。信頼関係構築と「言うべきことを言う」は両立可能 ✏️ 要件定義は向き合いと一緒にテキスト化 ダッシュボードやレポート作成の依頼時、「どの目的で、どの観点で、なぜ見るのか」を向き合いと一緒に書き残せるレベルで整理。これを省くと要件が固まる前に着手することになり、双方にとって手戻りが発生しやすい 🏗️ データ基盤整備のタイミングを常に評価 早すぎても空振り、遅すぎても移行コストが跳ね上がるのが基盤整備の難しさ。スプシ主体のモニタリングが積み上がってから着手すると、現行オペとの二重管理で身動きが取りにくくなる 🎁 外注保守カット案件は中長期運用主体を確認 「外注の保守費用削減のためにDA側で巻き取る」相談は、一度立ち止まって中長期の運用主体を一緒に確認したい類の案件。自分が異動・退職したときの移管コストが高く、長期の保守タスクとして残り続けやすい。特にdbt等が絡むものは要注意 💡 私はこの切り替えが遅れ、後から上流に意見を出し始めた際に向き合いとの期待値調整が必要になりました。 ⚠️ 整備のタイミングをDA側から提案しきれず、暫定的な参照・運用が一部残っています。軽いうちに議論を持ち出すことが重要。 🟠 Month 3-6: 中長期伴走パートナーへのギアチェンジ 🎯 特に効いた3つ: 事業責任者+GM+bizops週次MTG立ち上げ / OKR策定シンクロ / 能動的価値発揮へシフト アクション 内容と効くポイント 🗓️ 事業責任者+GM+bizops 週次MTG立ち上げ 組織全体で優先順位を棚卸しする会議体をDA側から提案して立ち上げると、横断の判断軸を持って動けるようになる。この会議体は、2事業目が入ったときの司令塔にもなる 🎯 OKR策定タイミングにシンクロ 期初のOKR策定に合流して、事業側と「何を課題と捉えるか」をすり合わせ。これをやると、その後の依頼について目的を事前にすり合わせた状態で動けるようになる 🔀 GM経由のコミュニケーションフロー 現場の複数メンバーからは似た観点の依頼がそれぞれ届くため、個別にすり合わせていると工数が膨らむ。GM(またはbizops・集約役)経由のフローに整えると、定義の議論が一つの場に集約され、双方のコミュニケーションコストが抑えられる 🎤 能動的価値発揮へシフト 受け身で依頼を捌くフェーズから、DA起点で価値を提案するフェーズへ。例: 現場担当者(CA等)へのインタビュー設計で定性課題を抽出 / 事業責任者・GMが意思決定に使う経営ダッシュボードをDA起点で設計・提案 💡 ここからが新規事業DAの本領発揮ゾーン。事業の意思決定に直接関われるようになり、自分の分析・提案が事業の方向づけにつながる手触り感を強く感じられます。 🔴 2事業目が追加されるタイミング 🎯 特に効いた3つ: 熱量シグナル検知→能動介入 / ログ設計レビュー最優先 / 要望窓口の最初からの設計 アクション 内容と効くポイント 🌡️ 熱量シグナル検知 → 能動介入 新しい領域が熱を帯びる瞬間(目標変更・予算変更等)をDAが能動的にキャッチして動くことが重要。待っていると後手に回り、Part 1 ②の罠(介入前に実装が固まる)にはまる 🔍 ログ設計レビューを最優先 プロダクト駆動型事業なら必須。Part 1 ②を2度繰り返さないためにも、最初期から計測設計のレビューに入る関係性を作りに行く 🚪 要望窓口の体制を最初から設計 1事業目の学び(GM経由フロー)を即座に転用。人材紹介領域で「GM経由フロー」が効くと学んだので、DR領域では初期から意識的にGM経由フローを設計した 🗓️ 横断の優先順位会議体を再設計 2つ目以降の事業が入るタイミングを会議体再設計のトリガーにする。1事業目向けの会議体を拡張して、横断優先順位を扱える形に変えていく 💡 DR領域で目標が跳ね上がる動きを検知し、自分から事業責任者+PdMに働きかけて週次定例への参加を勝ち取りました。これがなければ今の伴走体制は立ち上がっていません。 Part 3: 全体を貫く2つの原則 これまでの話は2つの原則に集約できます。 原則① 未来を見据えた動きをせよ 「今が楽に回るから」で意思決定しない。 半年後のオペレーション・組織・関係性を想像して、初動で先手を打ちます。 データ基盤整備のタイミングを早めに見定める 初期から事業責任者との接点を作る KPIや優先順位の構造を、組織が大きくなる前に整理する 「目先の困りごと解決 → 中長期伴走パートナー」の移行を意図的にデザインする 新規事業は成長スピードが速く、"今困っていないこと"が半年後に大きなコストとして返ってくることが頻繁に起きます。 原則② 統制構造(要望窓口)を早期に組め 現場にbizops相当の集約役がいるかで、新規事業DAの難易度は桁違いに変わります。 いなければDA側から「誰が集約役を担うか」を提案するのが、DAの重要な仕事です。 統制構造が組めると、依頼フロー・優先順位付け・コミュニケーション工数のすべてが好転。逆にここが組めないと、どんなに優秀なDAでも個別対応だけで手が回りきらなくなります。 おわりに 落とし穴を中心に書きましたが、新規事業のDA伴走は半年経った今、自分のキャリアで最も学びと手触り感のあるフェーズだと感じています。「新規事業DA、ちょっと面白そう」と感じてもらえたら本望です。 最後に改めて、本記事の失敗エピソードはすべて、私自身(DA)の動きで改善できる余地について書いたものであり、事業側の皆さんを批判する意図はありません。急成長する新規事業の中で常に最善を尽くしてくださっているCareer Plus部の皆さんと、前任のDA・bizopsの方々に深く感謝しています。 この役回りに関する再現可能なノウハウはまだ少ない領域です。多くのDAが同じ試行錯誤を繰り返している現状が変わるきっかけになれば嬉しいです。 最後に、タイミーでは一緒に働くメンバーを募集してます!ご興味があればぜひお話しましょう! プロダクト採用サイトTOP カジュアル面談申込はこちら
こんにちは。株式会社タイミーのバックエンドエンジニアの神山(@dak2)です。 2026/4/22 から 24 まで函館で開催された RubyKaigi 2026 に参加し、Day 2 に登壇しました。 タイミーでは、世界中で開催される技術系カンファレンスに無制限で参加できる「Kaigi Pass」という制度を活用し、8名が現地でカンファレンスに参加してきました。 登壇内容や参加セッションで得た学びは各レポートにまとめています。気になった方はご覧いただけると幸いです。読者の皆様の今後の学びの参考になれば嬉しいです。 tech.timee.co.jp tech.timee.co.jp tech.timee.co.jp Road To RubyKaigi 2026 地震や飛行機の遅延などもありましたね。皆様の中にも、移動に戸惑った方いらっしゃったのではないでしょうか。 色々大変でしたが、参加者の方々が無事到着されたのを X(旧Twitter)で見て、一安心したのを覚えています。 印象に残ったセッション A Faster FFI rubykaigi.org 自分が作っている gem で Ruby と Rust を使っており、FFI 周りが気になっていたので聞きました。 FFIは、引数の数の確認や型変換(アンボックス)を実行時に行う必要があるため、C拡張に比べてオーバーヘッドが大きいようです。また、ピュアなRubyで書かれたJITコンパイラのFJITはC拡張より速いものの、CRubyの内部データ構造に強く依存していました。そのため仕様変更に弱く、実用的ではなかったとのことです。 FJIT これですね。fjit.rb · GitHub これに加え、アーロンは hacks gem というものを作っていて、そこから CRuby の 構造体を引っ張ってきて FJIT で使っているみたい。AST をダンプして構造体の名前を元にデータ構造を抽出、メモリのレイアウト情報を計算して Ruby のハッシュに格納して返してるみたいですね。 面白いなー。すごい力技だw FJIT はこのハッシュに依存しているから実用的ではなかったとのこと。 新たな解決策として ffx という gem を作ったみたいです。 Ruby の値を C に変換してネイティブ関数を呼ぶ impl 関数と、実際のコードへジャンプするトランポリン関数を生成。トランポリン関数を生成する際に、アセンブリに impl 関数への jump 命令を書いておき、その次のメモリ領域にマジックマーカーや型情報、パラメータなどのメタデータを書き込んでおく。 通常の実行時には impl 関数へ jump するので、型情報などは読み込まれないけど、ZJIT でのコンパイル時にはマジックマーカーを検知してメタデータを読み取って最適化に使うとのこと。 このハックは単純にすごいなと思いました。感心しながら聞いていたのを覚えています。勉強になります。個人的に印象に残るセッションでした。 Lightning-Fast Method Calls with Ruby 4.1 ZJIT rubykaigi.org speakerdeck.com 行く末が気になる ZJIT ですね。速さは正義ということで、とても期待しています。そこで、このセッションを聞きに行きました。 今の ZJIT はメソッド呼び出し時に全てのパラメータを一度メモリにロードしてしまう課題があるみたいですね。 バックトレースや例外処理、ローカル変数読み込みなどでスタック上に正確なメタデータを残しておく必要があるためとのこと。 これに対し、Lightweight Frames が提案されていました。 メタデータの書き込みを遅延させ、書き込むフィールドを「JIT Return」の1つなど最小限に限定しつつ、メソッドコール時のメモリライトを削減すると。ただ、ローカル変数の処理や例外時の longjmp などをどうにかしていかないといけないみたいですね。帰ってきてから ZJIT の内部を読んでみています。 Matz Keynote なんか Matz が一番楽しそうだったなあと思う Keynote でした。Ruby という言語を作ってなお、まだ作りたいものがある。AI と一緒に作った Spinel を発表している Matz が楽しそうだった。AI Slop とか色々ありますが、作りたいものを作るって最高ですよね。最高にクールでした。非常にインスピレーションを受けた Keynote でした。 matz リツイート 登壇 登壇時の写真 special thanks to @ginkouno rubykaigi.org speakerdeck.com AI 時代の Ruby では、NoMethodError を静的に解析できたら良いのではないか、という内容で登壇しました。登壇は想像していた何倍も得るものがありました。 きっかけは「日常の疑問」だった このトークの種は、普段の業務で感じた引っかかりでした。型アノテーション付きの Ruby とそうでない Ruby を行き来していると、どうしても型チェックの遅さが気になります。一方で、AI Agent のコーディング能力が一気に上がったことで、「そもそも型をちゃんと書いていく ROI ってどうなんだっけ?」という疑問が、頭の片隅から離れませんでした。 この「気になり」を寝かせていたところ、CFP が1週間延長になった当日、サウナで急に像を結びました。よく「サウナで整うと閃く」と言いますが、実際は逆で、普段から問題意識を温めていたからこそ、たまたま緩んだ瞬間に繋がったのかなと思っています。整うどころではなくなり、速攻で帰りました。その後、寝る間も惜しんでアイディアを形にし、CFP を提出したのが懐かしいです。 「型ありの Ruby と型なしの Ruby、両方を日常的に書いている自分だからこそ立てられる問い」だと思えたことが、提出のモチベーションになりました。自分の業務の中の違和感は、思っている以上にトークの種になるんだなと。 gem を作って「持論」を形にした セッション内で発表した Method-Ray という gem は、コアロジックに Rust を用いています。命名は X-Ray から着想を得ていて、個人的にも気に入っています。「こうすればできるのでは」という仮説をもとに設計し、最小限で動くものを形にし、gem として公開しました。僕の持論やスタンスを gem に込めた上で CFP を提出しました。 株式会社mov の @pjocprac さんが型関連のセッション内容をまとめてくださっており、僕の発表内容にも触れてくださっているので、詳細に興味があればぜひご覧ください。 RubyKaigiで型まわりの内容をまとめたブログ書きました!RubyKaigi 2026 型まわり4セッション聴講メモ — AI コーディング時代の Ruby の型#RubyKaigi https://t.co/HZB5PJW7z0— Takeshi Watanabe (@pjocprac) 2026年4月27日 登壇して初めて得られた3つのもの 発表後、いろんな方に声をかけていただきました。「ここの型解析どうしてる?」「なんでそう思ったんですか?」「英語話せるんですか?」などたくさんお声がけいただき嬉しかったです。 自分の盲点を埋めるフィードバック 質問内容を受けて「自分の gem もこう直さないといけないな」と気づきが連鎖的に出てきました。一人だと気づきにくい視点に気づかせてくれるというのは良い機会だなと。 自分のスタンスを認識する 今回はスタンスを取った発表をしたのですが、それに対していろんな意見をもらえました。賛否両論あると思いますし、いろんな意見があると思いますが、同時に自分の立ち位置もはっきりしました。スタンスを取った発表をして良かったなと思っています。 アイデアの昇華 @okuramasafumi さんとは、いわゆる廊下の話で、「テストが十分速ければ AI が PDCA を回しやすくなって、それは型解析の近似になっているのでは」という方向性を議論しました。登壇内容を、登壇の外で次のテーマへと押し進めてもらえる感覚があり、これは登壇したからこそ発生した会話なんだと思うと、良い機会に恵まれたなと嬉しく思いました。 次にやりたいこと 今後は、Method-Ray の解析範囲を広げたいのと、RBS の Rust crate の利便性を高めたいですね。自分の gem で RBS のロードを Rust crate から行いたいなと思っています。また、廊下での会話の流れもあって、高速化にも気持ちが出てきています。登壇を経て、自分の中の「次にやること」のリストが、行く前より大きくなっています。 終わりに 今年の Kaigi も最高でした。運営の方々、本当に素敵な機会をありがとうございました。いろんな方と知り合えましたし、思考を深められました。ぼんやりと次にやりたいことが見えてきました。<a href="https://rubykaigi.o
はじめに はじめまして、プラットフォームエンジニアリング本部に所属している徳富(@yannKazu1)です。 みなさん、サプライチェーン攻撃って気にしてますか? npm パッケージの乗っ取り(ua-parser-js 事件)、GitHub Actions の改ざん(tj-actions/changed-files 事件)、依存パッケージへのバックドア混入(xz-utils 事件)……。ここ数年、OSS を取り巻くセキュリティの前提がガラッと変わってきています。正直、「いつ・どこから仕掛けられるかわからない」状況です。 しかもサプライチェーン攻撃って、攻撃側のコストが低いわりに被害範囲が広いのが厄介なんですよね。 そんなわけで、ECS Fargate 環境におけるサプライチェーン攻撃対策を整理してみようと思ったのですが、いきなり全部を洗い出そうとしてもカオスになるだけ。何かいいフレームワークはないかな……と探していたところ、Kubernetes の 4C セキュリティモデル(Cloud → Cluster → Container → Code) の考え方がそのまま使えそうだったので、これをベースにチェックシート的に整理してみました。 「うちの環境だとどこが手薄いんだろう?」を考えるときの参考にしてもらえればと思います。 おことわり: これをやれば完璧!というものではないです。あくまで「見通しよく整理するための道具」として 4C モデルを借りているだけなので、実際にどこまでやるかは環境やリスク許容度に応じて取捨選択してください。 整理に使う 2 つの軸 軸 1:4C セキュリティモデル —「どこを守るか」 Kubernetes の公式ドキュメントで紹介されている、クラウドネイティブセキュリティを 4 つの同心円レイヤー で捉えるモデルです。 参考: クラウドネイティブセキュリティの概要 | Kubernetes ┌─────────────────────────────────────────┐ │ Cloud(クラウド基盤) │ │ ┌─────────────────────────────────────┐ │ │ │ Cluster(オーケストレーター) │ │ │ │ ┌─────────────────────────────────┐ │ │ │ │ │ Container(コンテナランタイム) │ │ │ │ │ │ ┌─────────────────────────────┐ │ │ │ │ │ │ │ Code(アプリケーション) │ │ │ │ │ │ │ └─────────────────────────────┘ │ │ │ │ │ └─────────────────────────────────┘ │ │ │ └─────────────────────────────────────┘ │ └─────────────────────────────────────────┘ ポイントは 各レイヤーが外側のレイヤーの上に構築されている ということ。どれだけアプリのコードを堅牢にしても、基盤レイヤーのセキュリティが低い水準では守りきれません。だからこそ、特定のレイヤーだけに頼るのではなく、すべてのレイヤーを固める 多層防御(Defense in Depth) が基本方針になります。 ECS Fargate への読み替えはこんな感じです。 4C レイヤー K8s での意味 ECS Fargate での対応 サプライチェーン攻撃での主な攻撃面 Cloud クラウド基盤 AWS アカウント・IAM・ネットワーク IAM キー漏洩、ECR への不正 push Cluster オーケストレーター ECS クラスター・CI/CD パイプライン CI/CD アクションの改ざん、パイプライン侵入 Container コンテナランタイム Docker イメージ・Fargate タスク ベースイメージの汚染、OS パッケージへのバックドア混入、実行時の不正プロセス Code アプリケーションコード ソースコード・依存パッケージ パッケージ乗っ取り、typosquatting、悪意ある PR 軸 2:対策の目的 —「何のために守るか」 4C モデルは「どこを守るか」を整理するフレームワークですが、それだけだと対策が偏りがちです。そこでもうひとつ、 「何のために守るか」 という軸を加えてみます。今回は、セキュリティ対策を以下の 4 つの目的に分類して整理してみました。 目的 説明 考え方 🛡 予防(Prevention) 攻撃を未然に防ぐ そもそも悪いものを入れさせない 🔍 検知(Detection) 攻撃や脆弱性を発見する 入り込んだ・紛れ込んだことに気づく 🧱 封じ込め(Containment) 侵入後の被害を最小化する やられても被害を広げさせない 🔎 調査(Investigation) 何が起きたかを追跡する 事後に原因と影響範囲を特定する よくある落とし穴は 「予防」ばかりに意識が向いて、他が手薄になる こと。完璧な予防は不可能なので、入り込まれた後にどう気づいて・どう被害を抑えて・どう調べるか、まで含めて考えるのが多層防御の本質です。 この記事の構成 本記事では 目的(予防・検知・封じ込め・調査)を大項目 にして、それぞれの中で 4C のどのレイヤーに対する対策か を整理していきます。 🛡 予防(Prevention)— そもそも入れさせない 攻撃を未然に防ぐための対策です。「入口を塞ぐ」イメージですね。 Cloud:VPC Endpoint 概要: AWS サービスへの通信をインターネットを経由せずに VPC 内で完結させる。 防げる攻撃: 侵害されたタスクからの外部 AWS アカウントへのデータ持ち出し (Endpoint Policy で自社アカウントに限定) マルウェア感染後の C2 通信・情報送信 (Egress 全遮断下でも AWS サービスは利用可能) 漏洩した IAM 認証情報による外部からの不正アクセス (バケットポリシーで aws:SourceVpce を指定) 設定のポイント: S3 Gateway Endpoint(無料)は必須 ECR、SSM、Secrets Manager、CloudWatch Logs 用の Interface Endpoint を検討 Endpoint Policy で aws:PrincipalAccount を制限 リソース側ポリシーで aws:SourceVpce を指定 Cluster:CI/CD パイプラインのハードニング 概要: GitHub Actions など CI/CD で使うサードパーティアクションを、改ざんされない形で固定する。 防げる攻撃: GitHub Actions の改ざん(tj-actions/changed-files 事件のように、人気アクションのリポジトリが侵害されてタグが書き換えられるケース) バージョンタグの上書きによる 意図しないコードの実行 設定のポイント: GitHub Actions は通常 uses: actions/checkout@v4 のようにタグやブランチで指定しますが、これらは 後から書き換え可能 です。tj-actions/changed-files 事件(2025 年 3 月)では、攻撃者がメンテナーの認証情報を侵害し、既存タグを悪意あるコミットに向け直すことで、汚染されたアクションを使う CI でシークレットがビルドログに書き出されるという被害が広範囲に発生しました。一方、commit SHA でピンニングしていたユーザーは影響を受けませんでした(侵害期間中に対象 SHA へ更新していなければ)。 対策として、commit SHA でピンニングする のが推奨されます。 # Before(タグ指定 - 書き換えられる可能性あり) - uses: actions/checkout@v4 # After(commit SHA でピンニング - 改ざんされない) - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 Dependabot や Renovate Bot で SHA の自動更新を設定 permissions: で各ジョブの GITHUB_TOKEN 権限を最小化 OIDC を使った AWS 認証に切り替え、長期クレデンシャルを廃止 パブリックリポジトリでは特に注意:ビルドログが公開されるため、ログ経由のシークレット漏洩のインパクトが大きい サプライチェーン攻撃との関連: これは Container レイヤーの digest ピンニングと同じ思想です。「同じ名前で違うものを掴まされる」攻撃を防ぐには、暗号学的なハッシュで内容を固定するのが基本になります。 Cluster:Secrets の安全な注入 概要: DB パスワードや API キー等の機密情報を、コードへの直書きではなく SSM Parameter Store や Secrets Manager から注入する。 防げる攻撃: ソースコードやコンテナイメージへのシークレット埋め込み を防止 Git リポジトリの漏洩時に クレデンシャルが直接露出するリスク を排除 KMS 暗号化により、AWS アカウントが侵害されても 暗号化キーなしでは復号不可能 設定のポイント: "secrets": [ { "name": "DATABASE_PASSWORD", "valueFrom": "/fargate/myapp/database-password" } ] Cluster:ECS Exec の制御 概要: ECS Exec(コンテナへの対話的アクセス)を必要時以外は無効化する。 防げる攻撃: IAM クレデンシャルが漏洩した場合の コンテナへの直接侵入 本番コンテナへの 不正なコマンド実行 設定のポイント: ECS Exec の制御は、サービス(または RunTask 呼び出し)レベルと IAM レベルの二重で行うのが確実です。enableExecuteCommand はタスク定義のフィールドではなく、サービス(CreateService / UpdateService)または RunTask のパラメータです。 サービス定義(または RunTask 呼び出し)で無効化:enableExecuteCommand = false を明示。そもそもサービス側で受け付けない状態にしておく。AWS CLI でも aws ecs update-service --no-enable-execute-command のように切り替え可能です。 IAM で ecs:ExecuteCommand を Deny:ECS Exec 専用の API なので、これを Deny するのが最も直接的。なお ECS Exec は内部的に SSM Session Manager の通信レイヤー(ssmmessages API)を利用するため、より厳密に制御したい場合は、タスクロールに ssmmessages:* 系の権限が紛れ込んでいないかも確認する 必要時のみ一時的に有効化する運用フロー:踏み台用の専用サービスを別途用意し、調査時のみそちらを起動する運用が安全。 補足: 後述の封じ込めセクションで紹介する readonlyRootFilesystem: true と ECS Exec は 両立しない 点に注意してください。SSM agent がコンテナファイルシステムへの書き込みを必要とするため、ルートファイルシステムを読み取り専用にすると ECS Exec が動きません(AWS 公式ドキュメントでも明記されています)。本番では readonlyRootFilesystem: true + ECS Exec 無効化、調査用の踏み台サービスでは ECS Exec 有効化、と用途で使い分けるのが現実的です。 Container:ベースイメージの digest ピンニング 概要: Dockerfile のベースイメージ指定を、タグだけでなく digest(SHA256 ハッシュ)で固定する。 防げる攻撃: ベースイメージのタグ上書き攻撃(同一タグに悪意あるイメージを push) レジストリが侵害された場合の イメージ改ざんの検知 設定例: # Before(タグのみ) FROM ruby:3.3.0-bookworm # After(digest ピンニング) FROM ruby:3.3.0-bookworm@sha256:2e1e76e5b2... 運用のポイント: Dependabot や Renovate Bot で digest の自動更新を設定する digest がまだ付いていないイメージに digest を自動付与する pinning 自体は、現時点では Renovate のほうが運用面で先行(pinDigests プリセット)。Dependabot 側でも 2026 年 2 月に PR #14071 が dependabot-core 本体にマージされ、docker_pin_digests という experiment flag として実装されました。ただし experiment flag は Dependabot サービス側で段階的に展開されるため、GitHub.com の Dependabot で「タグだけのイメージに digest を新規付与する挙動」がデフォルトで使えるかはタイミング次第です(フラグの有効化状況によっては自分の環境で効かないこともある点に注意)。 現時点で「すでに digest 付き」のイメージに対する digest 更新は Dependabot でも問題なくできます。タグだけで運用しているイメージを一括で digest ピン化したい
はじめに タイミーでは、世界中で開催される技術系カンファレンスに無制限で参加できる「Kaigi Pass」という制度を活用し、8名がRubyKaigi 2026 in 函館に現地参加しました。 また今年はDay2に、タイミーから @dak2 さんが "No Types Needed, Just Callable Method Check" というタイトルで登壇しました。 本レポートでは、参加したエンジニアが注目したセッションごとに、ポイントや得た知見をまとめてご紹介します。 各セッションごとに内容を整理し、参加者自身の視点から学びや気づきをまとめています。読者の皆様にとって、今後の学びの参考になれば幸いです。 Surviving Black Friday: 329 billion requests with Falcon! rubykaigi.org Shopify社のSamuel Williamsさん、Marc-André Cournoyerさん、Josh TeeterさんがFalconを導入することでブラックフライデー・サイバーマンデー(BFCM)期間の合計3,290億リクエストを乗り切ったお話でした。 自身は普段Webのバックエンドエンジニアとしてユーザートラフィックのパフォーマンス課題について関心を持っており、その流れでFalconや基礎技術のAsyncにも興味を持っていました。 Falconの開発者であるSamuelさんから、本番稼働中の高トラフィックなプロダクトにFalconを導入する際のコストや注意点、そして得られる効果を聞けると期待して、このセッションを聴講しました。 前提として、FalconとはAsyncベースのRack互換Webサーバーです。 AsyncとはRubyの軽量スレッドであるFiberを利用した非同期I/Oフレームワーク(ノンブロッキングI/O)です。 github.com Falconは単一プロセスの中で複数のHTTPリクエストに対応するFiberを割り当てます。 FiberでI/Oが発生すると、処理を別のFiberに移すことで、大量のリクエストの処理を実現します。 OSネイティブのプロセスやスレッドではなく、Fiberで並行処理を実現するためメモリ効率が良く、PumaやUnicornと比較してランニングコストが低いという特徴があります。 セッションではFalconのアーキテクチャの解説と導入に伴う段階的なスケールテストを通して多くの課題を解決していった様子を発表されていました。 取り組みの結果、従前のUnicornよりもスループット・コアあたりのリクエスト数・レイテンシが改善し、冒頭にもあったBFCM期間の3,290億リクエストを捌き切りました。 まず最初に自分が抱いた感想として、プロダクトの課題を解決しつつOSSコミュニティへの還元を忘れないという点に感銘を受けました。 導入の過程でFalconに対して行われた改善は誰もが利用できるようになっています。 Falconを実際のプロダクトに導入し、入念なテストを重ねてブラッシュアップしたうえで、個社最適化にとどめずOSSとして誰もが使える形で公開し、Rubyコミュニティ全体へ還元する姿勢に、エンジニアとしてとても憧れました。 また、発表の中でスケールテストの重要性について強くお話をされていたのが印象的でした。 最近の自身の関心ごとの一つとして、以下にテストをしやすい環境を作るか・本番に近い環境でテストができるかというものがありました。 Shopify社は「Genghis」というツールを用いてこれを行っているそうなのですが、詳しい情報が見つけられなかったのでご存知の方がいれば教えていただけると嬉しいです。 また、同社のテックブログを読むと「Game Day」と称してスケールテスト以外にもカオスエンジニアリングや障害のシミュレーションなどかなり大規模で入念なテストを行っていたことがわかります。 shopify.engineering ユーザー増加やキャンペーン施策によるトラフィックの増加は、パフォーマンスだけではなくランニングコストという面においても重大な関心事です。そうした状況で、Falconは有効な選択肢の一つだと感じました。 実際に触ってみて他のRack互換アプリケーションサーバーとどのような違いがあるか試してみたくなったので、まずは自身のローカルのRailsでFalconを動かしてみようと思います。 FalconのRuby on Railsの導入に関しては2025年のKaigi on RailsのキーノートでSamuelさんが発表しておりこちらもおすすめです。 kaigionrails.org 志賀(@akitoshiga) Practical TypeProf: Lessons from Analyzing Optcarrot speakerdeck.com @mametter さんによる、Rubyの型解析ツールTypeProfを、Ruby製8ビットマシンシミュレータであるOptcarrotに適用し、偽陽性の型エラーをゼロにするまでに何をしたのかという話でした。 TypeProfは、最小限の型注釈でエラー表示、定義ジャンプ、補完を提供するエディタ支援ツールです。型検査機にはSteepやSorbetがありますが、TypeProfはそれらとは異なり、型注釈をほとんど書かずにコードから型を推論します。 偽陽性の型エラーの原因は、実行時の不変条件が伝わらず、コード上nilになり得る型に対するメソッド呼び出しによるもの、動的メソッドで解析自体が難しいものなどがありましたが、本発表ではそれらをどう見つけどう直したかというものをAIの活用も含めてお話しされていました。 原因調査の中で、AIがキーポイントの調査において有効であることが語られました。実装全体の把握やその中でも特に多く呼び出される処理の特定は人間が調査するにはコストが高く不向きであると思うので、その部分をAIが十分に代替できるというのは素晴らしいなと思いました。 一方で、RBSでの型付けはAI任せだと雑になりがちなので一部は自分の手で直したと語られていました。まだまだAIは万能ではなく、人間が有効に使えているかどうかを判断する必要があり、場合によっては人の手で修正することが必要であるというメッセージとして受け取りました。 話の最後には同氏が以前公開された記事を踏まえ、型を書かないRubyがAIコーディングとの相性が良い可能性について触れており、その中で型の役割についてもガードレールとして機能するとされていたが、定量効果については慎重に評価すべきではないだろうか、としていました。 今後の展望としては、まずは人間向けに改善を進めていき、AIの使い勝手が安定してきた頃にAIエージェントを助けるためのツールとしての改良も検討しているとしていました。 RubyがAIコーディングと相性が良いかもしれないという示唆は、Rubyをメインで使っている者として、今後も使っていく価値のある言語である可能性を示されたような安心がありました。一方で動的言語であるが故に実行時エラーの懸念が常に付き纏いますが、そこを少ないコストで軽減できるツールとしてTypeProfの進化には期待したいです。 Rubyにおける型は、人によって意見が分かれると思います。個人的には、「型はあるに越したことはない。しかし、自分でわざわざ型注釈は書きたくない」という意見です。TypeProfは僕のようなRubyistにとって理想のツールとなる可能性があります。 RubyKaigi後、早速TypeProfを試してみようと思いましたが、RBSでモジュールエイリアスを定義しているとエラーによりTypeProfが起動しない問題に遭遇したので、PRを作成しました。 github.com 今後も自分にできる範囲でTypeProfの進化に貢献していきたいです。 rhiroe(@buta_botti) Ruby Releases Ruby rubykaigi.org @hsbt さんによるRubyのリリースを支えるRubyによる仕組みづくりについての発表でした。 今回の発表で印象的だったのは、数値で示されたリリースプロセスの進化と「徹底してRubyを使い込むこと」でした。 かつてRubyのセキュリティリリース現場では、最大4つの安定版ブランチにパッチを当てるために複数名のコミッターが5〜6時間に及ぶ深夜作業をされていたそうです。インフラ構成管理やリリーススクリプト、各種自動化ツールをRubyで揃えて改善を進めたことで、それが今や1名が1時間程度の作業で完了できる体制になったといいます。自動化による効率性向上に加えて、緊急性が高いセキュリティパッチ対応におけるRubyコミュニティのアジリティが底上げされたと感じました。 更に、リリースの頻度についても、2022年の年間9回から2024年の15回へと約1.5倍に加速しています。hsbtさん自身が、Ruby 4.0以降は「2週間に1回の頻度でリリースする」という目標を立てられているといい、既にRuby 4.0リリース以降から10回のリリースが実現できているようです。テスト基盤はGitHub ActionsとRuby CIの2系統で運用され、GitHub Actionsには約120のworkflowが存在するなど、幅広いプラットフォーム・ビルドパターン・コンフィギュレーションを継続的に検証できる体制が紹介されていました。 特に、開発版Rubyにおけるパフォーマンス向上やメモリ削減などの成果を現行の安定バージョンに還元するバックポートの仕組みや、OIDC連携によるTrusted Publisher、Sigstoreを用いた署名など、Bundlerを含むエコシステム全体に最新のセキュリティ標準が組み込まれていくことが紹介され、Rubyエコシステムの揺るぎない技術的信頼を感じました。 RubyによるRubyのためのリリースプロセスの改善が、あらゆるRubyistへの良質なユーザー体験を形作っているのだと感じられる発表でした。 江田(@edy629s) Lightning-Fast Method Calls with Ruby 4.1 ZJIT speakerdeck.com こちらのセッションでは今後のRubyの進化には欠かすことのできないZJITに関する内容でした。 特にメソッドコールに関する詳細なアプローチについて話されていました。 このセッションは今回の会場で一番広いホールで行われたのですが、そのほとんどの座席が埋まっているという状態で始まりました。 これはRubyにおけるZJITの注目度の高さが伺えますし、ShopifyのJIT開発チームでもYJITの頃から活躍されているk0kubun氏のトークであることからも多くの人を集めたセッションとなったのだと思います。 セッションの内容はメソッドコールにおけるRuby内部のアプローチについてRuby VMとYJIT、そしてZJITについて比較を行いながら話されていました。 まず最初にZJITのメソッドコール最適化の方法はいかにmemory writeを減らすかということに主眼をおいていることがわかりました。 メソッドコールはコードの実行においては多くの割合を占めるものであり、ここの部分での最適化の積み重ねが最終的に大きな改善となりうる箇所です。 本セッションではmemoryに加えてregisterの活用とそれぞれの活用順序を組み合わせることで、YJITと比べてもより高効率な最適化を目指したことを個々のステップを丁寧に説明されていました。 私はこのセッションにおいて、情報工学において誰もが習うであろうmemory, registerの組み合わせがいかに重要かを改めて認識することになりました。 CRubyという巨大な処理系においてもコンピューターの基礎となるアーキテクチャを駆使することで改善を積み重ねられるという事実に、ZJITという大きな取り組みの中にも基礎ありき
1. はじめに DRE(Data Reliability Engineering)グループ のつざきです。タイミーのデータエンジニアリング部で、BigQuery / dbt / Cloud Composer / Looker といったデータ基盤の開発・運用をしています。 DREチームでは 2026 年 2 月から、AWS が提唱する AI-DLC(AI-Driven Development Life Cycle)というワークフローを運用しています。きっかけは、 1 月末に AWS 主催の研修「Unicorn Gym」で3 日間 AI-DLC を体験したことでした。 AI-DLC 自体とタイミー全体への波及は同部の橋本さんが、Operations フェーズ(リリース後の検証)の独自構築については同じ DRE G の chanyou さんが、それぞれまとめています。 3日間のUnicorn Gymが1ヶ月で組織を変えた —— データで見るAI-DLC導入の波及効果(橋本さん) 「リリース後」に向き合うAI駆動開発の実践(chanyou さん) 本記事はこれらの続編的な位置づけで、「DREチーム が Inception と Construction フェーズで何を実装・運用しているか」に絞って書きます。 対象読者: AI-DLC を個人ではなく、チーム(モブ)で運用したい開発/データ基盤チーム この記事の目的: 公式の想定(単一プロジェクト/個人運用)を、複数リポジトリ・リモートモブ前提に翻訳した実装パターンを共有する 扱わないこと: Operations フェーズの詳細、全社展開の話、AI-DLC の一般解説 TL;DR DREチームは 2026 年 2 月から AI-DLC を運用中 実装: Workspace + CLAUDE.md 読み替え、Intent 単位の運用 モブ: 1 日 3 ~ 4 時間のフルリモートモブ。狙いは「フロー効率(承認ゲートで止まらない)」「キーパーソンに頼らない(新基盤導入や新メンバー受け入れに効く)」「AI 出力の欠陥を集合知で減らす」の 3 つ 3 ヶ月の結果: Intent 完了が月 14〜17 件で推移、PR 数は維持、サイクルタイムに劇的な変化は見えず 記事の立ち位置: 公式に書かれていない実装の隙間(Mob、複数リポジトリ、パス読み替え等)を自分たちで翻訳した事例として記録 2. AI-DLC をざっくり AI-DLC の全体像は既出記事に譲り、本記事で後から使う概念だけ押さえておきます。 本記事での用語の使い方 Intent: 1 つのゴール(例: あるデータソースを BigQuery で使えるようにする) Unit: Intent を疎結合に分解した作業単位(DDD の Subdomain 相当。例: Terraform 追加、DAG 実装など) Ritual: モブでの儀式的な作業(後述の Mob Elaboration / Mob Programming / Mob Testing) Workspace: ドキュメントとルールを置く専用リポジトリ フェーズと成果物の階層 AI-DLC には 3 つのフェーズがあります。 Inception: 要件分析・設計 Construction: 実装・テスト Operations: デプロイ・監視 3 つの Mob Ritual 各フェーズには対応する儀式(Ritual)が定義されています。 Mob Elaboration(Inception): 要件分析・分解を全員で Mob Programming(Construction): 実装を全員で Mob Testing(Construction): テストを全員で いずれも、公式推奨は「物理集合 + 共有スクリーン + ファシリテーター」です。 Human Oversight = Loss Function AI-DLC は AI が実行主体、人間は各ステップで検証・承認する構造です。公式ペーパーの表現が印象的で: "Each step serves as a strategic decision point where human oversight functions like a 'loss function' - catching and correcting errors early before they snowball downstream." 機械学習の損失関数のように、人間のレビューが早期にエラーを補正する、というメタファーです。後の章でモブワークの話をするときに効いてきます。 3. 公式ドキュメントに書かれていない実装ギャップ chanyou さんの記事では、awslabs/aidlc-workflows リポジトリで Operations フェーズがプレースホルダになっている話が出てきます。実は Inception と Construction の側にも、公式の文書と実装の間にいくつかのギャップがあります。 awslabs/aidlc-workflows の構成 原典の awslabs/aidlc-workflows は MIT-0 ライセンスで公開されている、マークダウンのルールファイル群です。 aidlc-rules/ ├── aws-aidlc-rules/ │ └── core-workflow.md # ワークフロー本体 └── aws-aidlc-rule-details/ ├── common/ # 共通ルール ├── inception/ # Inception 詳細 ├── construction/ # Construction 詳細 └── operations/ # プレースホルダ ギャップ 1: ルール実装に Mob の記述がない AI-DLC 公式ペーパーでは Mob Elaboration / Mob Programming / Mob Testing が中核の儀式として定義されています。しかし原典のルールファイル群を mob で grep してもヒットしません。実装部分は「個人と AI エージェントが 1 対 1 で対話しながら承認ゲートを通す」構造になっており、Mob は想定されていない書き方です。 ギャップ 2: 公式チュートリアルは個人開発の例 AWS 公式ブログの実践記事 Building with AI-DLC using Amazon Q Developer のサンプルは、単一 HTML ファイルの川渡りパズルを個人で作る例だけで、モブで回す実演は出てきません。 ギャップ 3: 複数リポジトリの扱いが明確でない 公式は単一プロジェクト前提です。データチームのように「1 つの機能を作るのに複数リポジトリにまたがる」ケースへの具体的な示唆はほぼありません。 理念と実装の翻訳が必要 つまり、公式ペーパーに書かれた「Mob ワーク」や「複数チームでの協調」を実際に動かすには、自分たちで翻訳する必要があります。DRE では、各ギャップに対応する形で次のように対処しています。 ギャップ 1(Mob がルールにない) → モブでの意思決定を組み込み(章 6) ギャップ 2(単一 Intent 想定) → Workspace + CLAUDE.md 読み替え(章 4) ギャップ 3(複数リポジトリが薄い) → 複数リポジトリを 1 Intent でまとめる(章 5) 次章から具体に入ります。 4. DRE の実装: Workspace + CLAUDE.md 読み替え AI-DLC を Claude Code で回すために、DRE では次の構成にしています。 全体像(先に結論) ルール階層: aidlc-rules/(上流)→ .claude/rules/(上書き)→ CLAUDE.md(入口) パス読み替え: aidlc-docs/requirements.md を aidlc-docs/intents/<YYYY-MM>/<intent_name>/inception/requirements.md に読み替え Intent 箱: Intent ごとに独立したディレクトリ(intents/<YYYY-MM>/<intent_name>/) 状態管理: aidlc-state.md に Status と Code Repositories を記録 スキル化: Intent ライフサイクルを Claude Code のスキルで操作 以下、理由と詳細を順に見ていきます。 なぜこの構成なのか awslabs のリポジトリは単一プロジェクト・単一 Intent 前提で書かれていて、1 つの aidlc-docs/ ディレクトリに成果物を蓄積する想定になっています。 一方で DRE は、Intent という単位で開発を進めていて、完了した Intent もそのまま保存しています(後述しますが 2026 年 3 月は 14 件の Intent が完了しました)。Intent ごとに独立したディレクトリが必要になるので、パス読み替えが不可欠です。 ルール階層(継承構造) aidlc-rules/: awslabs/aidlc-workflows の中身をそのまま取り込む。手動変更禁止、/aidlc-rules-update スキルで上流追従 .claude/rules/: プロジェクト固有のルール。aidlc-rules のオーバーライドや追加ルールを置く CLAUDE.md: エントリポイント。プロジェクト概要とディレクトリ規則を最小限に記述 上流は変えない。プロジェクト固有の振る舞いは派生側で足す。オブジェクト指向の継承に近い発想です。 [入口] CLAUDE.md ├─ 参照: aidlc-rules/ # 上流(awslabs 同期、変更禁止) └─ 参照: .claude/rules/ # 派生(DRE 固有、オーバーライド+追加) パス読み替えの例 awslabs のルールは、成果物の置き場として aidlc-docs/ というパスを前提に書かれています。DRE ではこれを Intent ごとのディレクトリに読み替えます。 公式: aidlc-docs/requirements.md DRE: aidlc-docs/intents/<YYYY-MM>/<intent_name>/inception/requirements.md この読み替えは .claude/rules/aidlc-workflow.md に定義してあり、Claude Code が実行時に解釈します。ルール本体(aidlc-rules/)は触らずに、パスだけ派生側で書き換える構成です。 Intent ディレクトリの構造 1 つの Intent のディレクトリはこういう構造です。 aidlc-docs/intents/<YYYY-MM>/<intent_name>/ ├── intent.md # Intent の目的・受け入れ基準 ├── aidlc-state.md # Intent の状態管理 ├── audit.md # 監査ログ ├── inception/ │ ├── requirements.md │ ├── stories.md │ └── ... └── construction/ └── <unit_name>/ ├── functional-design.md ├── code-generation.md └── ... aidlc-state.md のカスタマイズ Intent の進捗追跡に使う aidlc-state.md は、公式テンプレートをベースに少し拡張しています。 Status: OPEN / SUSPEND / CLOSED の 3 値を追加 Assignee: 担当者 Code Repositories: 複数のコードリポジトリのブランチ状態を記録 この Code Repositories セクションが次の章(複数リポジトリ運用)の鍵になります。 スキル化 Intent のライフサイクル管理は Claude Code のスキルとして定義しています。 /aidlc-intent-start: 新規 Intent 開始 /aidlc-intent-continue: 既存 Intent の再開 /aidlc-intent-save: 作業内容を PR 化してマージ /aidlc-rules-update: 上流(awslabs)への追従 chanyou さんの記事では /inception のように AI-DLC のワークフローそのものを呼び出すスキルが紹介されています。一方、DRE では「Intent というライフサイクルの入れ物」をスキル側で担う構成にしています。どちらも awslabs のルールに乗りつつ、スキルで扱う粒度が違う、という関係です。 5. 複数リポジトリを 1 Intent でまとめる DRE のようなデータ基盤チームでは、1 つの機能を作るのに複数のリポジトリが絡みます。 典型的なワーク 例えば「ある外部 SaaS のデータを BigQuery に自動転送するパイプラインを構築する」といった Intent だと、以下のようなリポジトリにまたがる変更が必要になります。 GCP Terraform リポジトリ: IAM やデータセットの定義 Composer インフラリポジトリ: Cloud Composer や Secret Manager の Terraform Composer DAG リポジトリ: Cloud Run Job と Airflow DAG のコード dbt リポジトリ: staging モデル これを 1 つの Intent としてまとめます。まず Inception フェーズで全体の要件・設計を固め、その後 Construction フェーズで各リポジトリに Unit を切って進めます。例えば DRE の 2026 年 2 月に動かしたあるパイプライン構築 Intent では、4 ユニット・60 ドキュメント・6 PR で完了しました(規模感の一例として)。 ブランチ戦略の 2 階建て ドキュメントとコードで別々のブランチ戦略を使い分けています。 Workspace リポ: session/<intent_name>/<hex> という短命ブランチ。スキル呼び出し単位で切って都度 main にマージ コードリポ: feature/<intent_name> という長命ブランチ。Intent が完了するまで維持 Workspace 側はドキュメントの進捗を小さくマージして積み上げ、コードリポ側は実装が揃ったタイミングで main に入れる、という二層構造です。 aidlc-state.md に Code Repositories を記録 1 つの Intent が複数リポジトリに触るので、どのリポのどのブランチで作業しているかを aidlc-state.md に記録しておきます。 <pre class="code lang-markdown" data-lang="markdown" data-unlink
こんにちは、タイミーでSRE業務を担当している徳富(@yannKazu1)です。 先日、函館で開催されたRubyKaigi 2026に参加してきました。Ruby本体やパーサ、GC、JITといった「言語の中身」を深掘りするカンファレンスなので、普段アプリケーションコードよりインフラ寄りの仕事をしている自分が行って楽しめるのか、という気持ちも少しありました。ですが、結果としてとても楽しめたので、感想を書いておきます。 SREが行っても普通に楽しめた 普段の仕事はRailsアプリケーションを安定して動かしたり、スケールさせたり、観測したりすることが中心です。Ruby本体にコミットするわけでも、パーサを書くわけでもないので、専門外の話も多いだろうと思っていました。 実際、聞いていて全部の細部までは追えないセッションもありました。それでも、 普段ブラックボックスとして扱っているGCやランタイムの中身が、作っている人の口から語られる 他社のRails運用をやっている人たちと直接話せる このあたりだけでも参加する価値を感じました。 Day 1のブースが意外と良かった 参加されたことがある方ならわかると思いますが、Day 2以降はブース巡りが意外と慌ただしくなります。スタンプラリーで人が流れたり、セッションの合間で時間が限られていたり。 その点、Day 1はスタンプラリーがまだ始まっていないので、ブースが比較的空いていてゆっくり話せる時間帯でした。立ち寄っても順番待ちがほとんどなく、エンジニアの方とじっくり話せます。 RubyKaigiにはほぼ例外なくRailsを本番運用している会社さんがスポンサーとして出展しているので、SREとしては「他社さんのアーキテクチャや困りごとを直接聞ける場」として、これがかなり面白かったです。 Railsで完結する vs クラウドネイティブに振り切る 複数の会社さんと話して興味深かったのが、「Railsの中で完結させるか、AWSのマネージドサービスに切り出すか」の判断基準が会社によって全然違うことです。 Railsはよくできていて、ActiveJob + Sidekiq、ActiveStorage、ActionCableなどを組み合わせれば、大抵のユースケースはRailsの世界の中で完結します。わざわざクラウドネイティブなマネージドサービスに切り出さなくても、運用負荷を抑えながら回せるケースは多い。 一方で、「ジョブの遅延が事業KPIに直結するので、マネージドサービスに切り出して水平スケールを確実にしている」と話す会社さんもあれば、逆に「今のスタックで十分捌けているし、Rubyエンジニアが運用できる構成に揃えたほうが組織的に強い」と話す会社さんもありました。 技術選定の基準として挙がっていたのは、ざっくりこんな観点です。 スパイク耐性が事業上クリティカルかどうか 運用するチームのスキルセットと採用市場 コールドスタートを許容できるワークロードか RubyKaigiは登壇者も来場者もアプリケーションエンジニアが中心です。そのため、「Sidekiqのままいくか、それとも切り出すか」といったテーマひとつとっても、「アプリケーション側からどう見えているか、何が嬉しいかつらいか」という視点で語られていたのが印象的でした。 普段、SRE系のイベントで「インフラ側の都合」としてこの手の話を聞くことが多い私にとっては、この視点の対比が非常に新鮮に感じられました。 「正解は一つじゃない」と頭ではわかっていても、SRE目線とアプリ目線では同じ意思決定でも見えている景色が違います。両方の視点を持っておくことが大事だなと、改めて感じました。 AI活用の温度感 もう一つ、多くのブースでも話題になったのがAI活用です。プロダクトへの組み込み、社内開発フローへの導入、営業・カスタマーサポートへの活用と、レイヤーごとに状況が違っていて面白かったです。 特に印象に残ったのが、SmartBankさんのブースで展示されていた「スマートバンクで働くAI Agentたち」のポスターでした。アプリユーザー向けの「ワンバンフレンズ」(家計を読み解いて気づきを届けるAIアシスタント)、社内メンバー向けの「Ask! ワンバン」(自然言語で社内データを検索・分析する分析AI)、そして開発者向けの「Guardie」(エラーや異常を検知してログ・コード・変更履歴を横断して原因特定を支援する番犬AI)という三本立てで、ユーザー向け / 社内向け / 開発者向けの3レイヤーに対してそれぞれAIエージェントを配置しているのがすごく整理されていて印象的でした。 特にGuardieはSRE視点でめちゃくちゃ刺さりました。「2時間覚悟していた調査が10分で終わった」という社内の声が紹介されていて、これは障害対応におけるMTTR(平均復旧時間)を本質的に短縮しに行っている事例だなと。エラー検知 → ログ・コード・変更履歴を横断した原因特定までをAIに任せる、というのはこれから我々も作っていこうと思っていた仕組みが普通に動いていて、刺激を受けました。 ブース担当の方とは「どこまでをAIに任せて、どこから人間がやるべきか」「誤検知や暴走への安全装置をどう設計しているか」みたいな話までできて、こういう一次情報が聞けるのもRubyKaigiならではでした。 気になった話は、その後のアフターパーティでさらに深掘りできました。資料には載らない現場のリアルな知見が交換される場として、ブース + アフターパーティの組み合わせは、セッションと同じくらい価値があったと感じます。 参加したセッションを日ごとに振り返る ここからは、自分が参加して特に印象に残ったセッションを日ごとに紹介していきます。 Day 1: Exploring RuboCop with MCP (Koichi ITO さん) 1日目に聴いたのが、RuboCopコアチーム・MCP Ruby SDKチームメンバーのKoichi ITOさんによる、RuboCopとMCP(Model Context Protocol)を組み合わせる試みについてのセッションです。 これまでRuboCopは「人間」または「他のプログラム(CIなど)」をきっかけに実行されてきました。そこにAI時代になって、AIエージェントという新しい実行のきっかけが登場した、というのが導入の話です。生成AIとリンター/フォーマッターをどう組み合わせるか、Rubyで実装されたMCPサーバーをエージェントの隣で走らせるとどうなるか、という内容でした。 技術的には、 MCP SDKの構造(サーバーとクライアントそれぞれのSDKがあること) トランスポート層としてstdioとStreamable HTTPの2種類があり、用途で使い分けること HTTPトランスポートではセッション管理が肝になり、Pumaのようなスレッドモデル + シングルプロセス構成だと素直に動くが、複数プロセス・複数ホストに横断するとセッションの保持が難しくなること ただしStateless Mode(stateless: true)を使えば、Pumaの複数ワーカーやUnicornのような複数プロセス構成にも対応できること。ただしこれはリクエストごとに新しいtransportインスタンスが生成されるためMCP-Session-Idを共有できないという制約とのトレードオフであり、「セッション保持を諦める代わりに複数ワーカー/プロセスでもスケールできる」という割り切り あたりが特に勉強になりました。特にセッション管理の話は、MCPサーバーをWebアプリケーションとして本番に乗せようとすると、ロードバランサーやスケールアウトとの兼ね合いが出てくるという点で実践的でした。ステートフル/ステートレスをどう使い分けるかは、これから考えないといけないテーマになりそうです。 セッションの締めくくりで「LLMの確率的な性質を決定的なツールに組み込むことで、これまでの決定的なツールとは違う未来が描ける」という話があって、そこも印象的でした。MCPのサンプリング(サーバーがクライアント経由でLLM補完を要求する仕組み)や、Elicitation(実行中にユーザーへ追加情報を問い合わせる仕組み)といった機能は、ツールの形そのものを変えそうな予感があります。 スライド: https://speakerdeck.com/koic/exploring-rubocop-with-mcp Day 2: Chasing Real-Time Observability for CRuby (Shintaro Otsuka さん) 2日目で一番テンションが上がったのがこのセッション。CRubyの実行状態をリアルタイムに3D可視化するというツール「rrtrace」の話でした。 普通のプロファイラはサンプリングベースで、後から集計して結果を見る形が多いですが、このツールは「いまこの瞬間にCRubyの中で何が起きているか」を、複数スレッドのスタック状態として3次元空間にレンダリングしながら見せる、というアプローチです。デモを見せてもらった時、IRBに入力するたびにスタックが積み上がっていく様子がリアルタイムで見えて、純粋に「すごいものを見ている」という感覚になりました。 技術的なポイントとしては、 計測側のC拡張は軽量に保つ設計で、イベントの収集と転送に特化している イベントはTracePoint API(CALL / RETURN / INTERNAL_GC_ENTER / INTERNAL_GC_EXIT)や内部のスレッドイベント(INTERNAL_THREAD_EVENT、こちらはWindowsでは利用不可)から収集し、timestamp(60bit) + event type(4bit) + method id/thread id(64bit)の合計16バイトの構造体に統一 C拡張(計測側)とビジュアライザプロセスの間はOS管理の共有メモリ上のリングバッファで受け渡し ビジュアライザ側はCRubyのコアを使っていない別プロセスなので、可視化処理が重くてもCRubyの実行を直接ブロックしない スタックシミュレーションが重いため、Parallel Scanアルゴリズムで並列化している という設計でした。ただし、スライドのベンチマーク結果を見ると、rrtrace有効時は関数呼び出しスループットがplain CRubyの17%程度(73,417,127 → 12,760,131 calls/s、約5.9倍遅くなる)、Railsサーバーのrpsもplain CRubyの55%程度(203.19 → 110.84 rps)になるとのことで、計測のオーバーヘッド自体は「小さくない(not small)」とスライドでも明記されていました。TracePointフックのコストが支配的で、ここは今後の課題とのことです。 それでも、「重い処理を別プロセスに全部寄せる」というアーキテクチャの考え方は面白かったです。計測側はできるだけ軽く保って、分析・可視化は別のリソースでやる。この割り切りが設計をシンプルにしていて、きれいだなと思いました。 「現代のマシンは10コア以上あるのが普通で、CRubyが1コアで動くなら残りのコアを観測やビジュアライズに自由に使える」という、リソースの捉え方の話も新鮮でした。GVLがある世界での観測ツールの設計思想として、納得感が強かったです。 スライド: https://speakerdeck.com/whitegreen/chasing-real-time-observability-for-cruby Day 3: The Less-Told Story of Socket Timeouts (Misaki Shioi さん) 3日目に聴いたのがこれ。ソケットライブラリのタイムアウトの歴史と内部実装を、Issue/Commitを参照しながらRuby 4.0までの流れに沿って解説していくセッションでした。タイトルからして気になっていたけど、期待以上の内容でした。 Socket.tcp / TCPSocket.new には、 resolv_timeout (名前解決のタイムアウト) connect_timeout (接続のタイムアウト) そしてRuby 4.0で追加された open_timeout (全体のタイムアウト) の3種類があります。「この3つがなぜ必要で、どういう順番で導入され、どんな歴史的な紆余曲折があったのか」を、Issue/Commitを参照しながら丁寧に追っていく構成でした。 特に印象的だったのが、 まず Socket.tcp に connect_timeout が導入され、続いて Addrinfo.getaddrinfo への timeout および Socket.tcp への resolv_timeout が追加されたこと resolv_timeout と connect_timeout を両方指定しても、全体のタイムアウト時間は制御できない(複数アドレスに対して逐次接続を試行するため、合計時間が想定より長くなりうる) これらの問題を解決するために、Ruby 4.0で全体時間を管理する open_timeout が追加された という話の流れです。普段、HTTPクライアントのopen_timeout/read_timeout/write_timeoutを「だいたいこのくらい」で設定しがちですが、その下のレイヤーでは名前解決と接続が並行で走っていて、タイムアウトの組み合わせによっては想定と全然違う挙動になるということを、改めて意識させられました。 また、歴史的な経緯として特に面白かったのが、名前解決の中断可能化(interruptible)をめぐる話です。 getaddrinfo(3) はブロッキング呼び出しで、Ctrl+C でも中断できないという問題が長年ありました。これを解決するアプローチとして、まず2020年1月に「Addrinfo.getaddrinfo が timeout をサポートする」提案が行われ、そのパッチで Addrinfo.getaddrinfo に timeout、Socket.tcp に resolv_timeout が追加されると同時に、内部的に「GNU拡張のgetaddrinfo_a(3)が利用可能ならそれを使う」実装が入りました(getaddrinfo_a(3)はワーカースレッドで非同期に名前解決を行う仕組み)。その後2020年8月には「Make Socket.getaddrinfo interruptible」がマージされ、Socket.getaddrinfo の内部もこの getaddrinfo_a(3) を使うように利用範囲が拡張、さらに2020年9月には TCPSocket.new にも resolv_timeout / connect_timeout が追加され、名前解決を中断可能にする方向で進められました。 ところがその後、Rails ActiveJobの統合テストが失敗するようになったという報告が入り、調査の結果、fork後の子プロセスでgetaddrinfo_a(3)を呼び出すとハングすることが判明します。getaddrinfo_a(3)は内部で再利用可能なワーカースレッドを保持しているのですが、forkでコピーされる子プロセスにはワーカースレッドが存在しないにもかかわらず内部状態は「ワーカースレッドが待機中」のままになっており、これによってデッドロックが発生する、という仕組みでした。 2ヶ月以上の調査と回避策の検討を経て、最終的にはgetaddrinfo_a(3)の導入自体が撤回され、関連変更もrevertされました。その代わり、後に別アプローチとして「名前解決ごとに専用のpthreadを立ててgetaddrinfo(3)を実行する」方式(mameさん提案、ruby/ruby#8695)が採用され、こちらはrsock_getaddrinfo内に実装されることで、内部的にrsock_getaddrinfoを呼んでいるAddrinfo.getaddrinfoやSocket.getaddrinfoを含む幅広いメソッドで名前解決のブロッキング問題が解消された、という流れです。 外部API連携で「タイムアウトを設定したはずなのにハングする」「connect_timeoutを短くしたのに、複数アドレスがあるホストで合計時間が想定の何倍もかかる」みたいな経験がある人は少なくないと思いますが、まさにあれの背景にある話でした。タイムアウト設計の見直しや、Ruby 4.0以降はopen_timeoutを積極的に使っていくこと、テストでタイムアウト周りの挙動を確認しておくことなど、すぐに持ち帰れる学びがいくつもありました。 スライド: https://speakerdeck.com/coe401_/the-less-told-story-of-socket-timeouts リモートワーク時代の副次効果 もう一つ書いておきたいのが社内メンバーとの関係性の話です。 弊社エンジニアはリモートワーク中心で、普段の業務だと開発チームの全員と毎日話すわけではありません。SlackやZoomでは話すけれど、雑談ベースで「最近どう?」みたいな会話になりにくい人もいます。 それが、RubyKaigiで3日間一緒に過ごすと一気に距離が縮まります。一緒にセッションを聞いて、休憩中に「今のどう思った?」と話して、夜は飲みに行って、移動中に雑談する。この3日間の密度は、リモートでの数ヶ月分のコ
※ 2026年4月時点の情報です こんにちは、データアナリティクス部のkoyoです。2024年1月に「データアナリストの一日」という記事を書きました。あれから2年が経ち、分析の進め方がかなり変わったので、改めてお伝えできればと思います。 この記事で紹介するのは、AIへのプロンプトの工夫ではありません。AIが正しく動き続けるための環境を自分で設計した話です。 Before / After — 変わったのは「認知負荷の配分」 2024年の朝はこんな感じでした。Slackの通知を上から順に読んで、未読チャンネルを巡回して、カレンダーを確認して、「あ、あのスレッドに返信できていなかった」と気づく。情報を集めること自体に時間と集中力を使っていました。 2026年の朝は違います。出社するとSlack DMにブリーフィングが届いています。自分がやることは、それを読んで判断し、返信するだけ。 変わったのは作業の速さではなく、認知負荷の配分です。「何を見るべきか」を考える必要がなくなった分、「見たものに対してどう判断するか」に集中できるようになりました。 昨年からAIエージェント(Claude Code)に本格的に向き合ってきました。個人でも、データ収集・分析パイプラインの構築や、育児・家事を含めた日常オペレーションの自動化など、生活のあらゆる場面でAIとの協働を重ねてきました。 データの収集・加工・判断支援という一連の流れをAIと一緒に設計・運用する経験を積む中で、「この考え方は分析業務にそのまま適用できる」という手応えを得ました。それを業務環境に展開したのが、これからご紹介する仕組みです。 朝のブリーフィング — 8つの視点で1日を俯瞰する 毎朝、ブリーフィングが自動生成され、Slack DMに届く仕組みを構築しています。Claude Codeの /loop 機能(cronのようにコマンドを定期実行するスケジュール機能)を使い、毎朝決まった時間に実行される設計です。 カレンダーAPI、Slack API、Notion API、Google Tasks APIを横断して情報を収集し、8つの視点で1日を俯瞰できるブリーフィングにまとめます。この仕組みは既製品ではなく、API連携スクリプト、収集ロジック、検証ルール、Slackメッセージの整形まで自分で設計・実装しました。 朝のブリーフィング自動生成フロー 📅 朝ブリーフィング ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1. 今日の予定 ← カレンダーAPI連携 2. 要対応 ← Slack未返信検出 + TODO期限 3. チーム動向 ← 所属チャンネルの横断要約 4. 注目チャンネル ← 担当プロジェクト関連の要約 5. 依頼更新 ← Notionの対応依頼 + チーム連絡の更新 6. ナレッジ鮮度 ← 知識ベースの最終更新チェック 7. 目標進捗 ← 四半期個人目標のリマインド 8. TODO追加提案 ← 全セクション横断の見落とし検知 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ → Slack DMに自動送信 ブリーフィングのSlack DMスクリーンショット ブリーフィングの3つの工夫 ① Slackの確認漏れ防止 直近3日間の自分宛スレッドを取得し、最終発言者が自分でなければ「未返信候補」として検出します。ただ、スレッド返信ではなく別のメッセージで対応済みのケースもあります。そこで、同チャンネルの同日付近にある自分の発言をクロスチェックし、「対応済みなのに未返信と誤検知する」ケースを排除する仕組みにしています。 これだけで「あのスレッドに返信できていなかった」が大幅に減りました。 ② 複数ツールの文脈を自動で横断する ただ情報を集めるだけなら、各ツールを開けば済む話です。このブリーフィングの価値は、人間が毎朝手作業で確認するには現実的でない量の情報を、構造化して届ける設計にあると思っています。 複数のSlackチャンネルを同時に監視し、チームの動向と担当プロジェクトの最新状況を毎朝要約します。分析依頼については、Slackの通知だけでなくNotionの依頼ページの中身まで参照します。そのうえで、自分の担当領域に合致するものを自動で判定します。会議予定にはNotionの議事録リンクやSlackの関連スレッドを自動付与する設計です。 「この会議って何の話だっけ?」「この依頼は自分が拾うべき?」を自分で調べに行く時間がなくなりました。 ③ TODO提案で見落としを防ぐ ブリーフィングの最後に、「TODO化すべきだがまだ登録されていない項目」を提案する仕組みを組み込んでいます。そのために、複数の情報ソースを優先順位付きで横断します。自分が「あとで対応する」と保存したSlackスレッド、未アサインの分析依頼、自分宛の未返信スレッド、全社向けの対応依頼 — これらを順にチェックし、既存TODOのタイトルと照合して重複を除外した上で提案します。 各提案には、「なぜTODO化すべきか」の判断理由を付与する設計です。提案の前には必ずスレッド本文を読み、タイトルだけでは判断しないルールも組み込んでいます。さらに、過去にタイトルだけで誤った提案をしてしまった経験から、このルールを追加しました。 曜日に応じて変わる情報収集 ブリーフィングは毎日同じではありません。月曜日にはナレッジの参照目次を最新状態に更新し、月初にはデータ基盤に加わった変更点をまとめて取得し、週明けにはデータ基盤の週次変更サマリーが新しい情報として表示されます。業務のリズムに合わせて情報収集の範囲が自動で変わる設計にしています。 ブリーフィングを支えるナレッジ基盤 ブリーフィングが正確に動くのは、AIが参照できるナレッジベースがあるからです。 ブリーフィングを生成する中で、AIは毎朝いくつもの判断をしています。たとえば: 「この分析依頼は自分が拾うべきか?」 → 自分の担当テーマの定義を参照 「このナレッジは古くなっていないか?」 → 各ファイルの最終検証日を参照 「この未返信スレッドは本当に未対応か?」 → クロススレッド対応の判定ルールを参照 「この社内用語は何を指しているのか?」 → 部門横断の用語集を参照 これらの判断を一つひとつ仕込んでおくのではなく、「判断に必要な情報」をAIがいつでも参照できる形で整備しておくのがナレッジ基盤の役割です。 目的別にディレクトリを分け、全体では12カテゴリ・約250ファイルを蓄積しています。 knowledge/ ├── business-logic/ ← 担当領域の定義・用語・判定ルール ├── collaboration/ ← コミュニケーション運用ルール ├── data-dictionary/ ← データ基盤の構造 └── sql-patterns/ ← 分析で使う設計パターン・検証テンプレ 最初から整備されていたわけではなく、日々の業務の中で少しずつ蓄積してきました。最初は空でも大丈夫です。使うことで育っていきます。 ブリーフィングが毎朝正確に届くようになって初めて、「判断の材料をAIが自律的に参照できる状態」こそがこの仕組みの土台なのだと実感しました。同じ考え方は、日常のクエリ作成や資料作成など別の業務にも応用しています。 設計思想 — AIを信頼できる同僚にする3つの原則 この仕組みを作る中で、AIとの協働に大切だと感じた原則が3つあります。 AIを信頼できる同僚にする3つの原則 ① 推測禁止 — 知らないことは調べる ブリーフィングでは、自分宛の未返信スレッドを毎朝検出しています。「このスレッドは未返信か?」を判定するとき、安易に「最終発言者が自分でなければ未返信」と推測すると、同チャンネル内の別メッセージで対応済みのケースを誤検知してしまいます。AIが推測で結論を出すと、毎朝同じ誤通知が届き続ける — これが一番厄介です。「知らないなら調べる、調べていなければ使わない」をルールに組み込むことで、この誤検知は大きく減りました。 ② 検証付き実行 — 作ったら検証してから報告する 未返信候補を検出したあと、同チャンネル内で自分が別メッセージで対応済みでないかを必ずクロスチェックしています。ブリーフィングの各セクションも、出力前に整合性を検証するステップを必ず挟んでいます。「動いたから正しい」ではなく、「検証したから正しい」を積み重ねていく考え方です。 ③ ソース付き情報 — 出所のない情報は存在しないのと同じ ブリーフィングの全項目にソースリンクを必須にしています。「どこかで見た気がする」ではなく、リンクを辿れば原文にたどり着ける。これがAIの出力を信頼できる理由です。 仕組みがあるからAIの出力を信頼できる。信頼できるから判断に集中できる。同じ3原則は、クエリ作成や資料作成にもそのまま当てはまる考え方でした。 変わったこと・まだ変われないこと 変わったこと 朝の情報確認が5分で完了するようになりました。Slackの返信漏れも大幅に減りました。一番大きいのは、「自分から情報を見に行く」から「情報が届く」に変わったこと。その分、判断と行動に使える時間が増えました。 これから変わりたいこと 情報収集と検証をAIに任せられるようになった分、DAとしてより価値の高い仕事に時間を使えるようになってきました。たとえば、事業課題の構造化や仮説の設計、ステークホルダーとの対話などです。ただ、まだその変化の途中にいます。 一番の課題は、この仕組みがまだ個人最適にとどまっていること。チーム全体で活用できる形にしていくのは、今後の挑戦です。 まとめ 2年前は「データアナリストの一日」を自分で全部やっていました。今は、朝の準備が完了した状態で1日を始められる環境を設計しました。 AIの能力は日々進化していますが、それだけでは業務の質は変わらないと思っています。AIが正しく動くためのナレッジや、出力を信頼するためのルール、見落としを防ぐための検証など、こうした「環境」を人間が設計して初めて、AIは信頼できる同僚になる。逆に言えば、環境を設計する力がこれからのデータアナリストに求められるスキルなのかもしれません。 自分はこういう形を選びましたが、やり方は人それぞれだと思います。もし興味があれば、まずは普段使っているテーブル定義を1つ、Markdownに書き出してAIに参照させてみるところから試してみてください。推測で書かれたクエリとの違いに気づくと、面白いと思います。 AIの社会実装や企業での本格導入がさらに進んでいく中で、こうした運用のあり方も磨きをかけながら形を変えていくと思います。そのときにまた、続編を書けたらいいなと思っています。 環境設計という視点が、どなたかの次の一歩のヒントになれば嬉しいです。 We're Hiring! タイミーでは、ともに働くメンバーを募集しています! データアナリストのポジションも募集中です。カジュアル面談も行っていますので、少しでも興味がありましたら、お気軽にご連絡ください。 データ | 採用情報 |株式会社タイミー
こんにちは、タイミーのバックエンド/Webフロント基盤チーム マネージャーの新谷(@euglena1215)です。 先日開催された RubyKaigi 2026 に参加してきました。その中で特に気になったのが、Shopify の Alexandre Terrasa さんによる「Blazing-fast Code Indexing for Smarter Ruby Tools」という発表です。 この発表では rubydex という Rust 製の Ruby Code Indexer が紹介されていました。RubyLSP や Tapioca に統合することで最大10倍の高速化と2倍のメモリ削減を実現したという内容でした。また、Ruby ツールのための統一的なコードインデックス基盤としてのビジョンも示されていました。Shopify の Ruby DX チームが9名関わっているということで、Shopify への rubydex への本気度が伺えます。 発表の中では、Experimental ながら MCP サーバー(rubydex-mcp)も提供されていることが紹介されていました。Claude Code などの AI アシスタントからセマンティックにコードベースを検索できるようになっています。 AI Coding Agent にコードベースを調査させると、Grep → Read → また Grep…というループが延々と続き、トークンがみるみる消費されていきます。rubydex-mcp を使えば、クラス定義やリファレンス、継承ツリーといった構造的な情報を、1回の MCP ツール呼び出しで取得できます。そのため、このループを大幅に削減できそうです。 実際にどの程度効果があるのか、タイミーのバックエンドリポジトリで定量的に検証してみました。 rubydex とは rubydex は Shopify が開発した Ruby Code Indexer です。 github.com Rust 製の Indexer がコードベースを解析し、MCP(Model Context Protocol)サーバーとして以下のツールを提供します。 ツール 機能 search_declarations 名前によるファジー検索(クラス、モジュール、メソッド、定数) get_declaration 完全修飾名による定義情報の取得(ドキュメント、祖先チェーン、メンバー) find_constant_references 定数の参照箇所をコードベース全体から検索 get_descendants クラス/モジュールの継承ツリーを取得 get_file_declarations ファイル内の構造一覧 codebase_stats コードベース全体の統計情報 通常、AI Coding Agent がコードベースを調査する際は grep や find でファイルを探し、Read で中身を読み、また grep で次のファイルを探し…というループを繰り返します。rubydex を使うと、このループの多くが1回の MCP ツール呼び出しで完結できる可能性があります。 検証方法 概要 claude -p(Claude Code の非インタラクティブモード)を使い、rubydex あり/なし の2条件で同じプロンプトを実行し、トークン消費量と回答品質を比較しました。 検証環境 ツール:Claude Code CLI (claude -p) モデル:claude-sonnet-4-6 rubydex_mcp バージョン:0.1.0 対象リポジトリ:タイミーのバックエンド(モジュラーモノリス、70パッケージ) 条件の制御 外部要因を排除するため、以下の共通オプションを使用しました。 claude -p "<prompt>" \\ --output-format json \\ # トークン使用量を含む JSON 出力 --model sonnet \\ # モデル固定 --bare \\ # hooks, CLAUDE.md 等を無効化 --strict-mcp-config \\ # .mcp.json を無視し引数の MCP 設定のみ使用 --mcp-config <config> \\ # 条件別の MCP 設定 --tools "Read,Bash,Edit" \\ --no-session-persistence --bare で CLAUDE.md の自動読み込み等の副作用を排除し、--strict-mcp-config により MCP サーバーの有効/無効を制御しています。これにより、2条件間の差は rubydex の有無のみになります。 プロンプト rubydex のツール群が効果を発揮しそうな質問を5種類用意しました。 ID プロンプト class_hierarchy XXXモデルのクラス継承チェーンと、includeしているモジュールの一覧を教えてください。それぞれのモジュールがどのファイルで定義されているかも含めてください。 find_references YYYモデルがコードベース全体でどこから参照されているか調査してください。参照元をコントローラ、モデル、サービス等のカテゴリ別に分類して一覧にしてください。 descendants ApplicationRecordを継承しているクラスの一覧を取得し、packs/ディレクトリ配下のパッケージごとに何個のモデルが存在するか集計してください。上位10パッケージを表示してください。 method_investigation XXXモデルに定義されているpublicインスタンスメソッドのうち、名前に'status'を含むものをすべてリストアップしてください。各メソッドの定義場所(ファイルパスと行番号)と、そのメソッドが何をしているかの簡単な説明を付けてください。 codebase_overview このRailsプロジェクトのpacks/ディレクトリ配下のパッケージ構成を調査してください。各パッケージに含まれるモデル数、主要なクラス名を一覧にし、パッケージ間の依存関係で特に密結合なものがあれば指摘してください。 各条件 × 各プロンプトで5回ずつ、合計50回実行しました。LLM の出力は非決定的なので、複数回実行して平均を取ることでばらつきの影響を軽減しています。 結果 トークン消費量 プロンプト rubydex なし(平均トークン) rubydex あり(平均トークン) 変化率 class_hierarchy 144,076 85,958 -40.3% codebase_overview 1,187,722 664,761 -44.0% descendants 46,501 165,795 +256.5% find_references 770,404 332,369 -56.9% method_investigation 986,840 636,411 -35.5% 5つ中4つのプロンプトで 35〜57% のトークン削減 を達成しました 🎉 コスト・速度 プロンプト コスト変化 実行時間変化 ターン数変化 class_hierarchy -16.7% -48.6% -35.4% codebase_overview -34.3% -19.6% -13.7% descendants +294.6% +261.0% +62.7% find_references -33.5% -19.0% -11.9% method_investigation -30.7% -50.1% -38.1% ターン数(エージェントのツール呼び出し回数)の削減がトークン削減の主因です。rubydex のセマンティック検索が Grep → Read の繰り返しを置き換えることで、エージェントループが短縮されています。 回答品質(LLM-as-a-Judge) トークンが減っても回答品質が下がっては意味がありません。別の Claude セッションを立ち上げ両条件の回答を渡し、正確性・網羅性・有用性の3観点で5点満点のスコアリングを行いました。 プロンプト rubydex なし(平均) rubydex あり(平均) 差分 class_hierarchy 4.33 4.00 -0.33 codebase_overview 4.33 4.00 -0.33 descendants 3.00 4.67 +1.67 find_references 4.00 4.00 0.00 method_investigation 3.33 4.33 +1.00 平均 3.80 4.20 +0.40 回答品質はむしろ改善しています 👏 Judge のコメントから見えた傾向を簡単にまとめます。 rubydex ありで改善した点(正確性) rubydex なしの場合、grep の結果をもとに関連しそうなクラスやメソッドを補足情報として列挙する傾向があった。目視では誤情報は確認できなかったが、裏取りが不十分な状態で情報を出しているため信頼性の判断がしにくい(method_investigation など) rubydex ありではインデックスに基づいた情報を返すため、出力の根拠が明確になっている rubydex なしが勝った点(網羅性・有用性) grep ベースの調査は探索範囲が広いため、rubydex が返さないカテゴリ(Policy、Mailer 等)の参照元も拾えていた(find_references) rubydex なしの回答はファイルのフルパスや構造図を含むなど、開発者がすぐに使える形に整理されている傾向があった(class_hierarchy, codebase_overview) 総じて、rubydex ありは正確性で優位、rubydex なしは網羅性で優位という傾向が見られました。また、いくつかのプロンプトの回答を目視でも確認しましたが、rubydex ありで明らかにおかしな内容を回答しているケースは見られませんでした。 descendants が悪化したケース 唯一、descendants プロンプトではトークンが +256.5% と大幅に悪化しました。 このプロンプトは「ApplicationRecord の子孫クラスをパッケージ別に集計する」という内容です。rubydex の get_descendants ツールは全子孫を忠実に返します。(我々の環境では346クラス)一方、rubydex なしの場合は grep -r "< ApplicationRecord" のような検索で主要なものだけを拾うため、結果的にトークンが少なく済んでいました。 つまり、大量の結果を返すような網羅的な検索では、rubydex がかえってトークンを増やすケースがあります。ただし、品質面では rubydex ありの方が +1.67pt と最も大きく改善しており、正確性とのトレードオフと言えます。 まとめ 5つ中4つのプロンプトで 35〜57% のトークン削減 と 17〜34% のコスト削減 を達成しつつ、回答品質は LLM-as-a-Judge の評価で同等以上(5点満点で 3.80 → 4.20)でした。特に「クラスの参照元を探す」「メソッドの定義場所を調べる」といった構造的な検索タスクで効果が顕著です。 一方、全件取得のような網羅的検索ではトークンが増えるケースもあり、万能ではありません。rubydex が提供するツールの特性を理解した上で導入すると、より効果的に活用できそうです。 また、現状 rubydex-mcp を利用するには Rust ツールチェーン(cargo)が必要で、ソースからのビルドが求められます。開発環境の依存が増えることになるため、チーム全員が使える形に整備するかどうかはもう少し見極めたいところです。とはいえ、トークン35〜57%削減という効果は十分に大きく、rubydex-mcp への期待はとても高まる結果となりました。 検証の制約 今回の検証にはいくつかの制約があります。結果を解釈する際の参考にしてください。 --bare モードでの検証: CLAUDE.md 等が無効化されているため、通常利用時とはベースのトークン消費量が異なります キャッシュの影響: 実行順序や間隔によってキャッシュヒット率が変わるため、コスト比較は参考値です 回答品質の評価: LLM-as-a-Judge による自動評価のみで、正解データとの突合は行っていません プロンプトの偏り: rubydex が得意そうなタスクを選んでいるため、実際の利用での改善幅はこれより小さくなる可能性があります
はじめに こんにちは、株式会社タイミーでデータサイエンティストをしている藤井です。 普段は推薦システムの改善を担当しています。 早速ですが、皆さんは推薦モデルの改善実験を月に何本回せていますか? 仮説を立てて、実装し、実験し、結果を整理し、次を考える。 1サイクル回すだけでも、相応の負荷がかかります。片手間でサイクル数を増やすのは簡単ではありません。 しかし、もし「仮説を立てる」から「結果を整理する」までを AI が担えるとしたら? 実際に AI の案から改善が生まれています。しかも、人間が担うのは方針の選択、コードレビュー、実験の実行に絞れています。 では、実際にどれだけ回せて、どれだけ当たるのか? 人間が思いつかない切り口は出てくるのか? 私たちはそれを確かめるために、Claude Code の Skill 機能を使った半自動の実験プロセスを組み、実際に回してみましたので、紹介したいと思います。 先に結論 AI が出した改善案は 13件で、そのうち実験まで進めたのは 8件でした。 改善が確認できたのは 3件、横ばいが 2件、下落が 3件です。 打率だけを見ると突出して高いわけではありません。 ただ、人間が手を動かしたのは方針の選択、コードレビューと実験の実行だけで、それ以外は AI が担っています。通常業務と並行しながら、このサイクル数を回せたこと自体が、この取り組みのいちばんの成果でした。 モデル改善は 1回ごとの改善幅だけでなく、試行回数を増やせるかどうかが効いてくる領域です。 片手間で回せる仕組みがあれば、改善の累積速度が変わります。 解決したかった課題 AI に推薦モデルの改善案を聞くだけなら、チャットでもできます。 しかし、それを継続的な実験プロセスとして回そうとすると、運用上のボトルネックがいくつか出てきます。 長期記憶がない セッションが切れるたびに AI は過去の実験を忘れます。 同じ失敗を繰り返すリスクがあるだけでなく、過去の失敗を踏まえて次の方向を絞る、改善が出た方向を深掘りするといった、蓄積を活かした提案ができません。 コンテキストの無駄遣い 毎回生のログや大量のファイルを読ませると、トークンを消費するだけで、期待したほど精度も上がりません。 必要な情報を構造化して渡す仕組みがないと、コストだけが膨らみます。 これらを解決するために、Claude Code の Skill 機能を使って半自動の実験プロセスを組みました。 Skill と記憶の設計 このプロセスには 2種類の記憶があります。 knowledge(長期記憶) 過去の実験記録を構造化した Markdown ファイルとして蓄積するフォルダです。 各 Skill はここを読み、過去の試行を把握した状態から動きます。 実験結果はサマリとして圧縮されて書き戻されるので、サイクルを重ねてもトークン消費が膨らみにくい設計です。 scratch(作業記憶) サイクル途中の方針メモや実装の下書きなど、一時的な情報を置く場所です。 長期記憶に残すほどではないが、セッション内では参照したい情報がここに入ります。 また、AI のコンテキストウィンドウが圧縮された場合でも、ファイルとして残っていれば再読み込みで復元できるため、意図しないコンテキスト消失への備えにもなっています。 Skill Skill 自体には、参照すべきファイルパスやテーブル定義、コーディングルールに加えて、実験コストの前提、安全性チェックの観点、実装原則、過去実験との重複を避けるための自問自答リストなどを埋め込んでいます。 これにより、毎回ゼロから指示しなくても、各フェーズで必要な文脈と制約が揃った状態で AI が動けます。 また、長期記憶と作業記憶はリポジトリ上に存在するため、Cursor など別の AI ツールからも同じ情報を参照でき、Claude Code の提案を独立に検証することも可能です。 半自動実験プロセスの仕組み このプロセスは、上記の Skill と記憶の仕組みを使って構築しています。 1サイクルの流れ AI がテーブル定義やコーディングルールを確認する AI が過去の実験記録を読み、現状を把握する AI が次に試す改善案を複数提案する 人間が方針を選ぶ AI が実装する AI が変更の安全性を確認する AI が実施予定の内容を記録する 人間が実験を実行する AI が結果を記録に反映する 人間が手を動かすのは、方針の選択、コードレビュー、実験の実行だけです。 定義の確認、過去実験の整理、提案、実装、安全性チェック、記録は主に AI が担います。 実験結果 個別の実験内容の詳細は割愛し、ここでは改善幅の傾向のみを共有します。 13件の提案のうち、実験に進めなかった 5件を除いた 8件の結果です。 実験 主要な機械学習指標の改善幅(複数指標の範囲) A +2〜+7% B +0.5〜+3% C +1〜+3% D ±2%以内 E ±2%以内 F -3〜-7% G -3〜-6% H -35〜-20% 学び 以下はあくまで運用を通じた感想であり、厳密に検証された結論ではありません。 提案の方向性 変更が小さくなりがちな傾向がある。 AI に自走させると、実験結果の正確性を担保しやすい方向、つまり対照実験がしやすい最小限の変更に寄りやすい傾向がありました。 指示を入れると質が変わる。 「小さい改善ではなく構造ごと変える改善を考えてほしい」と明示的に伝えたところ、論文の知識を参照した鋭い提案が複数出てきました。AI の提案の質は、渡す制約や方向付けに強く依存します。 既存手法の非自明な応用が出てくる。 たとえば、DIN(Deep Interest Network)の target-aware attention を two-tower モデルに持ち込む提案がありました。two-tower では推論時に候補アイテムが不明なためそのまま適用できませんが、AI は「学習時だけ正例を attention query として使い、推論時はフォールバックする」という変形を考えました。この切り口自体、推薦チーム内では出ていなかったもので私たちには非自明でした。当然、学習と推論の不一致(train-serve skew)がリスクになりますが、提案自体にそのリスクと失敗した場合に何がわかるかが含まれていました。成功の保証はなく、失敗する可能性は高そうですが、失敗しても学びが得られる実験設計になっています。また、仮にこの方式がそのまま機能しなくても、事前学習フェーズでのみ target-aware に学習させるといった派生が考えられ、アイデアの種として意味のある提案でした。 壁打ち相手としては十分実用的だった。 厳密な比較をしたわけではありませんが、少なくとも今回の運用では、AI が出す提案は人間の壁打ち相手として十分実用的だと感じました。場面によっては、自分たちだけではすぐに出なかった切り口が出てくることもありました。 蓄積と学習 最も鋭い提案は最後に出てきた。 偶然の可能性はありますが、サイクルを重ねて過去実験の蓄積が増えたタイミングで、最も構造的な提案が出ています。蓄積が提案の質に寄与している可能性は否定できません。 過去の失敗を踏まえた推論が出てくる。 AI が提案を出す際に、「過去にこの実験は失敗したので、こういう可能性がある。だからこちらの方向を試してみましょう」といった推論のログを出してくることがよくありました。蓄積された記憶を参照しながら提案理由を組み立てている様子が見て取れます。 運用コスト 人間の作業時間の大半はバグ対応。 実験が問題なく動く回では、人間の仕事は方針を選び、コードをレビューし、実験を実行することに絞られます。一方でバグが出ると調査・修正・再実行に手を取られ、体感で人間の作業時間の 8〜9割はバグ起因でした。逆にいえば、バグが出た回を無理に立て直さず次の実験に進めば、手数自体はさらに増やせる可能性があります。実装にバグが出た実験案も、提案自体は knowledge に記録しておけば、AI のコーディング能力が向上した時点で低コストに再挑戦できます。 現時点でまだ分かっていないこと サンプルサイズが不足している。 この半自動改善プロセスを運用し始めたのは最近であり、実験数は 8 件です。ここから得られた傾向が一般化できるかは、まだわかりません。 長期記憶の効果は未検証。 長期記憶なしのフローと比較した実験は行っていません。蓄積が提案の質に寄与している可能性は示唆されますが、長期記憶が本当に効いているのか、それとも同じ品質の提案が記憶なしでも出るのかは、現時点では検証できていません。 まとめ このプロセスの価値は、AI が良い改善案を出すことそのものではなく、試行の回転数を上げられることにあります。 13件の提案から 8件を実験し、3件の改善を得る。個々の実験の改善幅は小さくても、改善を積み重ねれば累積的な効果は大きくなります。 つまり、モデル改善は打率ではなく打席数が効いてくる可能性が高い。この取り組みの価値は、試行錯誤を片手間でも継続して回せるようになる点にあります。 長期記憶の効果や AI の提案精度については、まだ言い切れることは多くありません。 ただ、少なくとも「AI に改善案を出させて回す」というサイクル自体は、実用的に機能しています。今後はサンプルを増やしながら、このプロセス自体の改善も続けていきます。 こうした推薦改善の試行錯誤や、評価・運用の仕組みづくりに興味がある方は、ぜひ以下もご覧ください。 We’re hiring! 現在、タイミーではデータサイエンスやエンジニアリングの分野で、共に成長し、革新を推し進めてくれる新たなチームメンバーを積極的に探しています! データ | 採用情報 |株式会社タイミー また、気軽な雰囲気でのカジュアル面談も随時行っておりますので、ぜひお気軽にエントリーしてください。↓ hrmos.co hrmos.co hrmos.co Reference Skillを作成するにあたっては、Y Combinator の Garry Tan さんによる gstack リポジトリ(MITライセンス)を大いに参考にしました。 GitHub - garrytan/gstack: Use Garry Tan's exact Claude Code setup: 23 opinionated tools that serve as CEO, Designer, Eng Manager, Release Manager, Doc Engineer, and QA · GitHub なお、本記事を書いている途中に、AI に継続的に作業させる方向の動きがいくつか出ていました。今回の取り組みと直接の関係はありませんが、同じ方向性の事例としてメモ的に置いておきます。 Automated Alignment Researchers: Using large language models to scale scalable oversight(Anthropic, 2026/04/14)― 9 体の Claude Opus 4.6 を自律的なアライメント研究者として走らせた実験。複数 AI に役割分担させて探索を回す、という方向の一例。 Introducing routines in Claude Code(Anthropic, 2026/04/14)― Claude Code にスケジュール実行や webhook トリガーで動かせる routines が追加。今回は Skill で手動起動していますが、こうした仕組みに載せれば定期的な提案・記録反映まで自動化できそうです。
はじめに こんにちは。タイミー プロダクトエンジニアの津守です。今年1月にタイミーに入社し、気づけば早3ヶ月が経ちました。 この記事では、入社して数ヶ月働いて感じた「AIツールがオンボーディングプロセスをどう変えたか」という体験をまとめます。技術的な深掘りというより、新しい環境に飛び込んだエンジニアの個人的な気づきとして読んでもらえると嬉しいです。 従来のオンボーディングプロセスのイメージ 新しい会社に入ったとき、多くのエンジニアは最初の数週間を ドキュメントを読む。コードベースを読む。アーキテクチャを把握する。チームの開発スタイルを理解する。そして、ある程度理解できたと感じてから、ようやく手を動かし始める。 というような順序で過ごしてきたと思います。 言ってみれば「インプット先行」の学習スタイルです。この期間は"情報を受け取る期間"と暗黙的に認識されていることが多く、アウトプットは後回しになりがちでした。チームへの貢献よりも、まず「追いつくこと」が優先されるイメージです。 AI活用によって感じた変化 入社して最も強く感じたのは、この「順序」が変わったということです。 AIツールを使うことで、コードベースへの理解が浅い段階でも、まず動くものを作ることが現実的になりました。実際Cursor や Claude Code を主体に実装を進めると、知識のギャップをAIがある程度埋めてくれます。おかげで、入社初期からチームメンバーやステークホルダーのレビューやフィードバックを素早く受け取ることができました。 実際、チームメンバーやステークホルダーからのフィードバックやレビューには、基礎的な知識だけでなく、「タイミーではこうやってる」といった暗黙のコンテキストが含まれており、ドキュメントから得られる知識に加えて、より多くの背景情報を得られる場面があります。 開発アプローチとして広く受け入れられているアジャイルでは、「いかに早くステークホルダーがレビューできる状態を作るか」が重要な論点のひとつです。これは、個人が環境に適応するうえでも重要な要件だと思います。完璧な理解を待ってから動くのではなく、まず動くものを見せてフィードバックをもらう。そのサイクルを素早く回すことが、結果的に最も効率的な学習を生み出し、属する組織で求められる行動を起こせるようになるために重要と考えています。 適切に学習サイクルが回るための条件 ただ、このアウトプット先行の学習サイクルが機能するには、2つの環境が整っている必要があると感じました。どちらもAIツールの登場で新たに生まれた課題ではなく、組織の開発体験として元々重要だったものですが、AIツールの発達によってその重要性はさらに増しています。 1. AIが適切なアウトプットを出せる環境 AIが出すアウトプットの質は与えるコンテキストに大きく左右されます。学習サイクルの中でフィードバックを通じて暗黙のコンテキストを受け取れるとはいえ、そもそも明示的に言語化されているほうが望ましく、AIのアウトプットの精度も上がります。 実際、タイミーではバックエンド開発Handbookを通じて、開発プロセスを明示的に言語化する動きがあります。設計・実装・運用にまたがるガイドラインが体系的にまとめられており、さらにそれがAIエージェントのスキルとして提供されています(詳しくは新谷さんの記事「バックエンド開発Handbookを届けるために ― AI時代の知の高速道路を敷く」をご覧ください)。 Handbookが生まれた背景のひとつには、メンバーの増加やAIツールの進化により、バックエンド以外のエンジニアが越境してコードを書く機会が増えたという事情があります。ただ実際に使ってみて感じたのは、暗黙知をまだ何も持っていない入社直後のメンバーにこそ、そのインパクトが大きいということです。「そもそも何を知らないかもわからない」状態でも、AIがHandbookに沿ったアウトプットを出してくれることは、単なる品質担保以上の意味を持ちます。 自分がHandbookを意識していなくても、AIがガイドラインに沿った設計や実装を提案してくれる——「気づいたらタイミー流の書き方になっていた」という感覚は、入社して間もない時期にとても心強いものでした。 2. フィードバックをもらえる環境・体制 もうひとつの前提条件は、フィードバックの環境です。どんなに早くアウトプットを出しても、適切なフィードバックが返ってこなければ学習サイクルは止まります。 この3ヶ月間は、チームメンバーやステークホルダーから丁寧なフィードバックをもらえる環境にあり、そのおかげで学習が加速しました。特に、PRベースのコードレビューは厳密に行われており、そこでの指摘やディスカッションがとても多くの学びになりました。 ただ、3ヶ月を通じて感じたのは、現状ではフィードバックの質が運用や状況によってばらつきが出やすい状態にあるということです。体制として担保されているというよりは、チームメンバーの意識や余裕に左右される面があり、持続的に機能させるには仕組みとしての設計が必要だと感じています。 もうひとつ、AIがアウトプットを加速させることで生まれるトレードオフも見えてきました。学ぶ側が早く動けるようになった分、レビューする側が見るべきPRの量も増えます。学習サイクルが速くなった恩恵が、レビュワーの負荷という形で偏在してしまうわけです。 また、PRベースのレビューは厳密に行われている一方で、暗黙知やコンテキストを深く共有したうえでのフィードバックを、どう生み出すかという問いも残ります。これらに対してモブプログラミングやペアプログラミングのような形式は有効な解のひとつだと思っていて、後からまとめてレビューするコストを分散させながら、よりリッチなフィードバックを生みやすい構造だと感じています。 持続的に相互フィードバックが行われる開発体制をどう設計するか——これはまだ答えの出ていない問いですが、AIが学習サイクルを高速化させるほど、フィードバックを循環させる体制の重要性は増していくと感じています。 おわりに 3ヶ月を振り返ると、AIは入社直後の学習の「量」を変えたのではなく、「順序」を変えた、というのが一番しっくりくる表現です。 以前なら「理解してから作る」だったものが、「作りながら理解する」に変わりました。この変化は、入社直後という時期をより能動的に過ごす後押しをしてくれると感じています。 ただし、そのサイクルを本当に機能させるには、AIが適切なアウトプットを出せる環境と、フィードバックを届ける体制という、人間側の設計が不可欠だと感じました。Handbookをはじめとした環境を整えてくれたチームには、改めて感謝しています。 同じように新しい環境に飛び込んでいる方や、新しいメンバーを迎える立場の方に、少しでも参考になれば嬉しいです。
こんにちは。タイミーでプロダクトエンジニアをしている福島(taishi)と大竹(otake)です。 EMConf JP 2026が3月4日に開催されました。 2026.emconf.jp タイミーは今年、EMConf JP 2026のスポンサーをさせていただきました。 タイミーには、世界中で開催されているすべての技術カンファレンスに無制限で参加できる「Kaigi Pass」という制度があります。今回はこの制度を使って参加しました。 詳細は以下をご覧ください。 productpr.timee.co.jp EMConf はエンジニアリングマネージャー(EM)向けのカンファレンスですが、私たちのようなマネジメントをしていないメンバーにとっても学びの多いイベントでした。 本記事では、印象に残ったセッションをいくつかピックアップしてご紹介します。 冒険する組織のつくりかた 著書「冒険する組織のつくりかた」を執筆された、株式会社MIMIGURIの安斎勇樹さんによるセッション。メンバーの興味傾向を把握し、目標と個人の動機を接続する場をデザインするための具体的なアプローチや、思考のフレームワークが紹介されていました。 目標のマネジメント:SMARTからALIVEへ 目標設定において、管理側の論理である「SMART」と、取り組む側の視点である「ALIVE」を両立させることが重要です。 SMARTの法則: 業務を精緻に遂行させるための指標(Specific, Measurable, Achievable, Relevant, Time-bound) ALIVEの法則: メンバーが前向きな意味を感じられる指標 Adaptive(適応): 変化に適応し、将来役立つ能力を身につけている安心感 Learningful(学習): 学びの機会となる Interesting(興味): 好奇心をそそる Visionary(未来): 未来を見据える Experimental(実験): 実験的な試みである さらに重要なのは、目標設定の「前」と「後」のプロセスです。目標を単に提示するのではなく、メンバーの内発的動機と目標を「ミート」させることが肝心です。 設定するまで: ヒアリングで意見を踏まえ、参加型デザインで一緒に考える 設定したあと: リーダーがストーリーテリングで意図を語り、ダイアログ(対話)で取り組む意味を共有する 興味のマネジメント:8つの「活動スタイル」 個人の「興味のツボ」を把握することで、目標にALIVEな要素を組み込めます。興味は「ヒト」か「コト」か、そして「どのレンズ(役割)で見るか」の組み合わせで8タイプに分類されます。 興味のレンズ ヒトに興味がある コトに興味がある 創造 新しいコミュニティやカルチャーを生み出したい 新しいプロダクトやビジネスモデルを創出したい 解明 人間の心理や集団の力学を明らかにしたい 現象のデータを分析し法則性を明らかにしたい 介入 人やチームに寄り添い、変化や成長を支援したい 現場の課題に働きかけ、状況を改善・解決したい 運用 秩序や制度を維持し、公平に運営したい 手続きを正しく回し、品質を保ちたい コメント これまで「SMARTの法則」に則った目標設定は意識していましたが、それは管理する側の視点でした。そのため、取り組む側のモチベーションの観点が不足しうる、という指摘が興味深かったです。SMARTとALIVE両方の観点を取り入れることで、メンバーが主体性をもって取り組めるようになり、結果的に目標達成の確度が上がります。生成AIの急速な進歩で目まぐるしく変化する世の中だからこそ、モチベーションを高く保ち、腰を据えて取り組める目標設定のアプローチとして、私も心がけてみようと思いました。(taishi) 数年後のキャリアプランを立てることに難しさを感じていましたが、「今この瞬間の興味(好奇心)」を起点にするというアプローチは非常に腹落ちしました。技術トレンドの移り変わりが激しいからこそ、無理に未来を固定するのではなく、自分の「好き」や「気になる」を組織の課題と接続し、適応しながら進んでいけるよう、前向きな気持ちで業務に取り組んでいきたいと感じました。(otake) 「ストレッチゾーンに挑戦し続ける」ことって難しくないですか? speakerdeck.com 成長には、現状のスキルで難なくこなせるコンフォートゾーンを抜け出し、適度な負荷がかかるストレッチゾーンに身を置き続けることが不可欠です。しかし、実際には「今の自分に最適な挑戦が不明」「日々の忙しさによる自然消滅」「外部要因による阻害」といった要因で、ストレッチゾーンに居続けることが難しい場合があります。本セッションでは、これらを克服するための環境設計が示されました。 現状分析: Will/Can/Mustのフレームワークに加え、具体的な事象を問い(Why)で抽象化し、新たなアクション(How)に繋げる「具体と抽象の往復」が重要 目標設定: コンフォートゾーンの誘惑を断ち切るための武器として、具体的で測定可能な「SMART」だけでなく、チームで共有・可視化され野心的な「FAST」な目標設定を活用する 仕組み化: マネージャーの支援前提ではなく、権限委譲やシステム思考(因果ループ図など)を用いて、組織として挑戦が推奨される構造を作る コメント 特に印象的だったのは、スナッキング(簡単で達成感はあるが学びが少ない仕事)の誘惑という概念です。忙しいときほど慣れた仕事に逃げてしまいがちですが、それを防ぐために自らFASTな目標を掲げ、周囲に宣言することで、意識的にストレッチゾーンに身を置く工夫を取り入れたいと感じました。 また、SMARTな目標は達成までの道のりが具体的にイメージできる反面、大きな成長につながる目標が生まれにくい側面もあります。これまでチームで目標を共有しても、協力体制が生まれたり切磋琢磨する状態になったりしにくかったため、その点でもFASTな目標設定を取り入れてみたいと思いました。(otake) 「事業目線」の正体 〜3つのフェーズのCTO経験から見えてきた、EMが持つべき視点 speakerdeck.com EMが持つべき「事業目線」を、3つのステップで具体化したセッションです。 Lv.1 数字を知る: 自組織に関わる数字(売上、MAU等)を把握し、事業予算の構造を因数分解して、自分のエンジニアリング組織がどこに作用しているかを理解する Lv.2 お客さまと隣接組織を知る: 数字の裏にある「なぜそうなっているか」を知るために、お客さまの声(生の声)を聞き、経理・営業・CSといった他部門の力学(大切にしていること)を理解する Lv.3 戦略に反映する: 得られた知見をエンジニアリング戦略や組織の仕組み(ダッシュボード化や研修等)に落とし込み、「明日」の大きな問題を解決するために「今日」何をすべきかを決める。 コメント 事業目線という言葉の解像度が劇的に上がったセッションでした。特に隣接組織の構造を知ることで、自分の開発が他部署のオペレーションにどう影響するかまで想像を膨らませるという視点は、シニアなエンジニアを目指す上で欠かせないものだと痛感しました。また、何のために開発しているのかを改めて考えてみて、価値を最大化できるように日々の行動を変えてみたいと思いました。まずは自分のチームに関わる数字を言えるようにするという小さな一歩から始めてみます(otake) 技術的負債の泥沼から組織を救う3つの転換点 speakerdeck.com 著書「アーキテクチャモダナイゼーション 組織とビジネスの未来を設計する」の翻訳を担当された、株式会社スリーシェイクのnwiizoさんによるセッション。技術的負債は「技術」の問題ではなく、組織構造やプロセスの問題が技術的な問題として表出したものだと捉え、モダナイゼーションを推進する手法が紹介されていました。最初に組織に学習する構造を持たせ(転換点1)、次にどこに集中投資するかを意思決定者の言語で語り(転換点2)、最後に不確実性を受け入れつつ小さく始め、学習するサイクルを作る(転換点3)。そのための手法や考え方について詳細に解説いただきました。 転換点1:学ぶ力(組織に学習する構造を持たせる) 組織が自律的にシステムとビジネスの構造を理解し、学び続ける状態を作る段階です。AMET(Architecture Modernization Enabling Team)を触媒として、イベントストーミングやワードリーマッピングなどの手法を活用しつつ、チームが自律的に学習を続けられるようになるまで支援します。 転換点2:語る力(意思決定者の言語で投資判断を促す) 技術的な課題を「コードが汚い」といった技術者の言葉ではなく、経営や事業の成長を阻害する「ビジネスリスク」として翻訳する段階です。Core Domain Chartで自社のドメインを「差別化度」と「複雑性」の2軸で整理した上で、それを事業の選択肢の制約として提示することで、経営層が自分の判断軸で技術投資を評価できる構造を作ることが重要です。 転換点3:始める力(不確実性を受け入れ、小さくサイクルを回す) 成果を出しながら段階的に変革を進める段階です。1つのバリューストリームで小さく始め、3〜6ヶ月以内にモダナイゼーションの第一歩となる成果を出すことを目指します。逆コンウェイ戦略に基づき、理想のアーキテクチャに合わせて組織構造も同時にデザインします。 コメント モダナイゼーションにおける具体的なステップと実践的な手法が紹介されており、とても良質なセッションでした。変革の推進力を高めるだけでなく、変化を阻む摩擦を取り除く重要性とアプローチについても語られており、現場目線で参考になりました。「モダナイゼーションで最も難しいのは着手すること。2番目に難しいのは勢いを維持すること」という言葉も印象に残りました。チームがいかに強い意志をもって持続可能な変化を続けられるかが最重要だと感じています。著書「アーキテクチャモダナイゼーション 組織とビジネスの未来を設計する」もぜひ読んでみたいです。(taishi) まとめ 今回のEMConf JP 2026では、エンジニアリング組織における幅広いテーマが取り上げられていました。 メンバーの視点でも、今この瞬間の興味を起点にした成長戦略、ストレッチゾーンに身を置くための仕組みづくり、事業の数字や隣接組織への解像度を上げることなど、自身の成長とチームへの貢献を加速させるヒントが詰まっていました。 EMConfという名前ではありますが、エンジニアリングに関わるすべての人にとって価値のあるイベントだと感じています。 得られた知見を日々の業務に活かして、個人と組織の両方で成長できるように努力したいと思います!
はじめに タイミー QA Enabling Gの矢尻、岸、松田です。 ソフトウェアテストに関する国内最大級のカンファレンス「JaSST (Japan Symposium on Software Testing) ‘26 Tokyo」が、2026年03月20日に開催されました。 タイミーには、世界中で開催されるすべての技術カンファレンスに参加できる「KaigiPass」という制度があり、この制度を利用してオフラインで参加しました。 jasst.jp 今年の会場は東京ビッグサイトでした。 本レポートでは、印象に残ったセッションの内容を中心にお伝えします。 JaSST Tokyo 2026 参加レポート — AI駆動QA時代の到来とタイミーの現在地 タイミーの矢尻です。 今回のJaSSTは、前回にもから増してAI関連セッションが圧倒的に多い回でした。基調講演からクロージングまで、ほぼすべてのトラックでAIが議論の軸となり、AI駆動開発における品質保証(QA for AI-Driven Development = QA4AIDD)が業界全体のメインテーマに昇格した印象です。 タイミーでは社内のQAガイドライン「QA Handbook」を通じてAI時代のQA戦略を先行して整備してきました。本レポートでは、セッション横断で見えた 3つの業界トレンド と、タイミーの取り組みとのフィットギャップを総論的にまとめます。 セッション横断で見えた3つのトレンド 今回、私が視聴したのは以下の6セッションです。 AIがテストチームに加わるとき- 期待、落とし穴、そしてソフトウェア品質の未来 – スペシャルトークセッション『AIと品質保証のこれまでとこれから』 AIがQAエンジニアの仕事を奪うのか? 生成AI時代、ソフトウェア品質保証のロールと組織はどこへ向かうのか? 品質を経営にどう語るか 人と関わるロボットの研究開発 –ロボットにおける人間らしさの重要性 – 横断すると、業界の議論は大きく 3つのテーマ に収束していました。 1. AIへの「プロセス要求」と人間の監督 複数セッションで共通して語られたのは、AIに「何を作るか」だけでなく「どう作るか」を明示する必要性です。 ベリサーブ様のセッションでは「ハーネスエンジニアリング」として、AIにプロセス要求を与えアクティビティログでオーディットするアプローチが紹介されました。SIG SQAの井芹様は「HITL(Human-in-the-Loop)」と「Everything as Code」をキーワードに、人が適切なポイントで介在するプロセス設計の重要性を強調。安野様のセッションでは、AIが一次スクリーニング(リコール向上)を担い、人間がコンテキストを踏まえた精査(プレシジョン向上)を行う「2層スクリーニング」モデルが示されました。 基調講演のGayathri Mohan様も、AIは「ベビーシッター」のように常に監視と調整が必要な存在であると指摘しており、「AIに任せきりにしない品質保証のプロセス設計」が業界の最大関心事になっていることを強く感じました。 2. リリース後の継続的品質バリデーション もう一つ、独立した複数セッションで繰り返し言及されたのが、プロダクション環境での継続的モニタリングです。 ベリサーブ様のセッションでは「フライホイール型品質保証」として、リリース前で完結せず本番環境で継続的にスコアを監視→フィードバック→再リリースを回す「運用型QA」が提唱されました。Adobe様の小島様もAIエージェント評価において、事前テストだけでは限界があり実データでの課題探索が不可欠だと強調。基調講演でも、非決定論的なAIの出力に対して確率論的・メトリクスベースの評価が必要だと語られました。 リリース後の品質バリデーションは、もはや「やるかどうか」ではなく「いつ・どう始めるか」のフェーズに入っていると感じます。 3. 品質を経営の言葉で語る 3つ目のトレンドは、品質と経営の対話です。 kyon_mm様らのセッションでは、品質を「技術の詳細を説明する場」から「事業の優先順位を決める場」に移すための翻訳プロトコルとして、バランススコアカード(BSC)、Cost of Quality(COQ)、NIST AIリスクマネジメントフレームワークの3つが示されました。ベリサーブ様のセッションでも「QAエンジニアは経営の意思決定に必要な情報を提供する立場に移行する」という見通しが語られ、SIG SQAの伊藤様も「事業戦略と連携した品質戦略策定」を高度化すべきスキルとして挙げていました。 作業をAIに委ね、QAエンジニアの役割がより上流・経営(ビジネス)寄りにシフトしていくという方向性は、セッションを跨いだ一貫したメッセージでした。 タイミーQA Handbookとのフィットギャップ タイミーでは「QA Handbook」として、3つの戦略(Business Reliability / Standardized Process / AI-DLC & QaC)を柱にQA活動を体系化しています。上記の業界トレンドと照合した結果を整理します。 ✅ フィットしている領域 業界潮流 タイミーの対応 評価 Everything as Code / AIフレンドリーな成果物 Gherkin/Markdownでの仕様標準化+教師データ蓄積 先行 HITL型プロセス設計 Generative Testing Pipeline(Human=意思決定、AI=実装) 先行 プロセス要求+オーディット DoR/AC/DoD+壁打ちリファインメント 同期 AI×人間の分業テスト設計 テスト仕様書生成(AI一次生成→人間レビュー) 同期 リスクベースドテスト ISTQB準拠のRPN分析を体系的に整備済み 先行 ⚠️ ギャップがある領域 業界潮流 現状と推奨アクション 優先度 リリース後の継続的品質バリデーション 構想済みだが未着手。CUJベースの指標でスモールスタートすべき 高 品質活動のビジネス価値換算(BSC / COQ) エラーバジェット概念をCOQ文脈で再定義するアプローチが有効 高 AIエージェント評価の体系化 4テスト種類×二軸評価指標を自社AI評価に応用可能 中 非決定論的テストへの対応 パイプラインに統計的評価レイヤーの追加設計が必要 中 まとめ JaSST Tokyo 2026を通じて確信したのは、タイミーのQA Handbookが掲げる方向性は業界潮流と高い整合性を持っているということです。Everything as Codeによる教師データ蓄積、HITL型のプロセス設計、リスクベースドテストの体系化は、業界が「これからやるべき」と議論しているものを先行して体系化できています。 一方、最大のギャップは「リリース後の継続的品質バリデーション」と「品質活動のビジネス価値換算」 の2点。いずれも複数セッションで繰り返し言及され、業界コンセンサスが形成されつつあるテーマです。 今回のJaSSTは、AI駆動開発が「一部の先進企業の取り組み」から「業界標準の議論テーマ」に移行したことを実感する場でした。先行して整備してきた資産を活かしつつ、ギャップの解消に取り組むことで、QA4AIDDの実践をさらに一歩進めていきます。 開発チームとの協業とトレーサビリティ基盤 タイミーの岸です。私からは印象に残った二つのセッションの紹介と感想をお届けします。 開発チームとQAエンジニアの新しい協業モデル:年末調整開発チームで実践する [QAリード施策] / SmartHR speakerdeck.com SmartHRの平澤さん・依田さんによる、開発エンジニアとQAエンジニアとの協業の取り組みについての講演でした。 開発チームによる自律的なQAを支援する施策であり、QAエンジニアが開発チームに入り込んで、最初はQAについて支援しつつ最終的にはチームから抜けていくというものです。 特徴的なのは、チームに参加するQAエンジニア以外に、チーム内からもQAを推進するメンバーを立てるという点でした。このメンバーは「QAリード」と呼ばれ、QAエンジニアとの1on1やチーム内での旗振り、テスト技法の勉強会などを通してQAプラクティスを根付かせていきます。QAリードの役割は目標設定にもきちんと反映されていくとのことでした。人選は指名ではなくチームからの立候補を基本とする形とのことで、SmartHRの開発チームにおける品質意識の高さがうかがえました。 こういったチームの自律性支援はタイミーでも実践の真っ最中です。QAリードの役割やQAエンジニアからの推進の方法など、私たちにとっても参考になる点が多く、とても興味深く聴かせていただきました。 仕様漏れ実装漏れをなくすトレーサビリティAI基盤のご紹介 / コインチェック speakerdeck.com コインチェックの国分さんによる、ドキュメント間のトレーサビリティとそれを検査する基盤についての講演でした。 ドキュメント間には関連性があります。例えば、要求からは仕様が派生し、仕様からは設計、設計からは実装が、また設計からはテストケースも派生します。このため、派生元と派生先は矢印で結ぶことでグラフとして表現できます。ここで、矢印の片方にドキュメントが存在しなかった場合は「アノマリー」となり、何かがおかしいことがわかります。派生先が存在しなければ、実装やテストが漏れている可能性があり、派生元が存在しなければ不必要な成果物が作成されている可能性があるということです。そして、コインチェックではこのグラフを検証するシステムをAIを活用して作っているとのことでした。 AI基盤については、可能な限り人手を抑えつつ、偽陽性・偽陰性を抑えるためのチューニングが行われていました。一方でAIを並列して稼働させるためには何よりも金銭コストがかかり、これを抑えるために敢えて軽量なモデルを使用するなど苦慮されている様子でした。 タイミーにおいては、ドキュメントを作成するかどうかチームによるバラツキがあります。そのためこういった検証基盤については、同じものを作っても定着するかどうかは未知数です。とはいえ、複雑化している仕様をどのように管理していくかは私たちにとっても大きな課題です。こういった取り組みを参考にしつつ、自分たちにマッチする仕組みを開発していくことは重要であると感じました。 要求・暗黙知・越境から見る AI 時代の QA タイミーの松田です。 昨年はタイミーとして登壇する側でしたが、今回は一参加者として様々なセッションに参加し多くの学びを得ることができました。 今回の JaSST Tokyo では AI と QA に関するトピックが多く、参加したセッションにはそれぞれ共通するテーマがあると感じました。私はその共通項を 3つ に整理しました。 要求エンジニアリング — QA の基礎能力としての重要性 暗黙知 — AI への適切なコンテキスト提供 越境 — エンジニアリングと QA の役割の進化 本レポートでは、それぞれの学びについてまとめます。 1. 要求工学(エンジニアリング )— QA の基礎能力としての重要性 こちらは、freeeの苅田さん・栗田さんが発表された「曖昧な要求は仕様かバグか-―ai時代の仕様とテストを考える」の発表から得た学びです。 ここでは「要求工学(エンジニアリング)」 に関しての発表を軸に話が進みました。 カンファレンスでは要求工学に関する発表があり、その重要性が改めて強調されました。 プロダクトには必ず何かしらの価値が求められます。その価値を言語化し、プロジェクトとして具体化するためには、要求を適切に言語化 → 仕様を策定 → 設計に落とし込む というフローが欠かせません。この流れは、AI を活用する時代になっても変わらない本質的なプロセスです。 AI がどれだけ進化しても、「なぜ作るのか」が不明瞭もしくは曖昧であれば、意図通り・要求通りのプロダクトを作ることは困難 です。作るべきものの目的と価値を明確にすることは、AI 時代においても変わらず重要な技術です。 シフトレフトの流れの中で、QA エンジニアは 要求事項の適切性を検証する 役割を担います。要求が適切でない場合、そこには暗黙の前提や仮定が隠されている可能性があります。要求獲得などの技法を活用し、暗黙知を明確に引き出して、必要な情報から作り上げていくことが求められます。 2. 暗黙知 — AI への適切なコンテキスト提供 二つ目は 「暗黙知」 です。 こちらは、チームみらいの安野さんとテクバンの豊田さん・長島さんによるセッション「AIがQAエンジニアの仕事を奪うのか?」から得た学びです 現在、AI をできる限り活用し、精度を上げて素早く価値を出すことが大きなトピックになっています。この流れは今後も変わらないでしょう。 しかし、AI に意図通りの価値を出させるには、適切なコンテキストを渡すこと が不可欠です。そのコンテキストは私たち人間から情報として伝達されます。つまり、どのような情報をどう入力するかが、AI を最大限に活用するための鍵になります。 ここで重要になるのが、暗黙知の言語化、つまり「暗黙知を形式知に変えること 」です。人間が持つ暗黙知をできる限り言語化し、AI が学習・認識できる状態にする必要があります。 会話やメール、Slackなどのやり取りをログとして集めることも、コンテキストを得るうえで有効だと話されていました。 また、先ほどのfreee様の発表でも相手の真の要求を知るためにヒアリングするなどの「要求獲得」といった話題とも繋がると感じました。 3. 越境 — エンジニアリングと QA の役割の進化 三つ目は 「越境」 です。 チームみらいの安野さんから「QA もエンジニアも、今後同じ作業をし続けるわけではなく、その 業務内
はじめに こんにちは。タイミーのデータアナリティクス部でデータアナリストをしているishidaです。普段は、タイミーのプロダクトに関する分析業務に従事しています。 タイミーのデータアナリスト(DA)チームでは、プロダクト施策の効果検証としてABテストを頻繁に実施しています。ABテストの業務は、大きく「実験設計」「クエリ作成」「可視化・レポート」の3工程に分かれますが、これらすべてをDAが担当しています。 施策の数が増えるにつれ、ABテストの “回転数” がボトルネックになりつつありました。そこで私たちは Claude / Cursor を活用し、まず実験設計のレビューを自動化する取り組みを始めました。 本記事では、その仕組みと設計思想をご紹介します。 なお、タイミーにおけるABテストは「① 実験設計 → ② クエリ作成 → ③ 可視化・レポート」の3ステップで進みます。本記事で扱うのは、①の実験設計レビューの自動化です。 1. 実験設計レビューの自動化 課題:レビューの属人化 ABテストの実験設計にはいくつかの重要なチェックポイントがあります。 チェックポイント 確認内容 SUTVA TG/CG間でリソースの奪い合いが起きないか Unit Alignment ランダマイズ単位とメトリクス集計単位は一致しているか SRM サンプル比率のミスマッチを検知できる設計か Novelty/Primacy 経時的変化を考慮した期間設定か Multiple Testing 多重比較の問題を制御できているか Guardrail 副作用を監視するガードレール指標は定義されているか これらのレビューは経験や前提知識によって見落としが生じやすく、属人化しがちでした。 解決策:AIによるチェックリストレビュー 私たちは、実験設計チェックリストを Claude / Cursor のコンテキストに含め、実験設計ドキュメントを入力するとチェックポイントごとにレビューが返るようにしました。 具体的には、以下の2種類のファイルをプロジェクトのルールとして設定し、AIに読み込ませています。 実験設計ドキュメントのテンプレート: テスト概要・テスト設計・評価指標などの項目が定義されたMarkdown チェックポイント定義: 6つの観点それぞれについて「判定の観点」「よくある違反例」「対応方針」を構造化したドキュメント AIレビューの出力イメージ ## CP1: SUTVA ⚠️ リスクあり -TG/CG間でリソースの奪い合いが発生する可能性があります -推奨: クラスタ単位でのランダマイズを検討してください ## CP2: Unit Alignment ✅ 問題なし -ランダマイズ単位と集計単位が一致しています ## CP3: SRM ✅ 設計済み -Debugging Metric として介入の影響を受けない指標を設定 -カイ二乗検定を実験開始時に実行する設計 ... ポイント:AIレビューは「最低限の品質保証」として位置づける 重要なのは、AIレビューを 人間のレビューの代替 としてではなく、最低限実行されるべきレビュー として位置づけていることです。 AIレビュー = チェックリストの網羅的な確認(漏れ防止) 人間レビュー = ビジネスコンテキストを踏まえた判断(例:この施策ならSUTVA違反は許容範囲か) これにより、レビュー依頼を受けたDAは「AIが見つけた問題点」を起点に議論できます。 学び AIレビューは「ゲートキーパー」ではなく「下書き」 AIレビューの結果を鵜呑みにせず、「少なくともこのレベルのレビューは済んでいる」という 品質の下限保証 として使っています。最終判断は必ず人間が行います。 この位置づけにしたことで、「AIに任せて大丈夫か」という心理的なハードルも下がります。 We’re Hiring! 私たちは、ともに働くメンバーを募集しています!! データアナリストの募集ページはこちら カジュアル面談も行っていますので、少しでも興味がありましたら、気軽にご連絡ください。
はじめに こんにちは。プラットフォームエンジニアリングチームに所属している徳富(@yannKazu1)です。 新規プロダクトを立ち上げるとき、インフラ構築って意外とやることが多いですよね。その中でも地味にめんどくさいのがDBユーザーの作成と権限付与。手動でやると「あ、権限つけ忘れた」「このユーザー名スペルミスってない?」みたいなヒヤリハットが発生しがちです。 今回は、この作業をTerraformでIaC化した話を書いていきます。 背景:ボイラープレートでインフラ構築を爆速にしている 弊社ではTerraformのボイラープレートと、それをもとにインフラを構築するためのDevinへの指示プロンプトをセットで管理しているリポジトリがあります。 新規プロダクトのインフラが必要になったら、このリポを使ってDevinにお願いするだけ。数時間もあれば、AWSアカウントの作成、VPC・ECS・Auroraなどの基盤構築、Terraform実行に必要なIAMロール・バックエンド・CI/CDワークフローの設定に加え、Datadog設定、監査設定、ログ基盤の作成まで、必要なインフラがひととおり立ち上がります。 このボイラープレートを整備するにあたって目指したのは、「Devinにお願いするだけで、新規プロダクトのインフラを簡単に作れる状態」でした。ところが、DBユーザーの作成だけはどうしても手動作業が残ってしまっていました。 せっかくDevinに投げれば数時間でインフラができるのに、DBユーザーだけは人間が踏み台経由でDBに繋いで CREATE USER して GRANT して……とやらないといけない。これだとボイラープレートの意味が薄れてしまいますし、手動オペレーションにはミスのリスクもあります。 ここをTerraformでIaC化できれば、ボイラープレートにサクッと組み込めて、Devinに任せるだけでインフラ構築が完結するようになります。 なぜTerraform? DBユーザーの管理といえばAnsibleを使うパターンも考えました。ただ、弊社のインフラは基本的にTerraformで一元管理しているので、できればTerraformの中で完結させたい。ツールが増えると学習コストも運用コストも増えますし、ボイラープレートにAnsibleのステップを追加するよりも、Terraformモジュールとして組み込む方がシンプルです。 というわけで、Terraformでなんとかする方向で調査を進めました。 Aurora Data APIという選択肢 弊社ではAurora MySQLを使用しており、バージョン3.07以降でRDS Data APIに対応しています。 Data APIは、HTTPSエンドポイント経由でSQLを実行できるAPIです。従来のようにVPC内から直接DBに接続する必要がなく、AWS CLIやSDKからサクッとSQLを叩けます。 これを terraform_data リソースの local-exec プロビジョナーと組み合わせれば、Terraformの中からDBユーザーを作成できるというわけです。 モジュールの実装 実際に作ったTerraformモジュールを紹介します。 DBユーザーの作成・削除 resource "terraform_data" "db_user" { input = { rds_cluster_arn = var.rds_cluster_arn rds_secret_arn = var.rds_secret_arn database_name = var.database_name username = var.username ssm_parameter_name = var.ssm_parameter_name } provisioner "local-exec" { command = <<-EOT PASSWORD=$(aws ssm get-parameter --name "${self.input.ssm_parameter_name}" --with-decryption --query 'Parameter.Value' --output text) aws rds-data execute-statement \ --resource-arn "${self.input.rds_cluster_arn}" \ --secret-arn "${self.input.rds_secret_arn}" \ --database "${self.input.database_name}" \ --sql "CREATE USER IF NOT EXISTS '${self.input.username}'@'%' IDENTIFIED BY '$PASSWORD'" EOT } provisioner "local-exec" { when = destroy command = <<-EOT aws rds-data execute-statement \ --resource-arn "${self.input.rds_cluster_arn}" \ --secret-arn "${self.input.rds_secret_arn}" \ --database "${self.input.database_name}" \ --sql "DROP USER IF EXISTS '${self.input.username}'@'%'" EOT } } ポイントは以下のとおりです。 terraform_data リソースを使って、local-exec プロビジョナーでData API経由のSQLを実行 CREATE USER IF NOT EXISTS で冪等性を担保 when = destroy のプロビジョナーで、terraform destroy 時にユーザーを自動削除 パスワードはSSM Parameter Storeから取得(後述の工夫で安全に管理) 権限の付与・取り消し resource "terraform_data" "db_grant" { for_each = { for idx, grant in var.grants : idx => grant } depends_on = [terraform_data.db_user] input = { rds_cluster_arn = var.rds_cluster_arn rds_secret_arn = var.rds_secret_arn database_name = var.database_name username = var.username privileges = each.value.privileges grant_database = coalesce(each.value.database, var.database_name) grant_table = coalesce(each.value.table, "*") } provisioner "local-exec" { command = <<-EOT aws rds-data execute-statement \ --resource-arn "${self.input.rds_cluster_arn}" \ --secret-arn "${self.input.rds_secret_arn}" \ --database "${self.input.database_name}" \ --sql "GRANT ${self.input.privileges} ON ${self.input.grant_database}.${self.input.grant_table} TO '${self.input.username}'@'%'" EOT } provisioner "local-exec" { when = destroy command = <<-EOT aws rds-data execute-statement \ --resource-arn "${self.input.rds_cluster_arn}" \ --secret-arn "${self.input.rds_secret_arn}" \ --database "${self.input.database_name}" \ --sql "REVOKE ${self.input.privileges} ON ${self.input.grant_database}.${self.input.grant_table} FROM '$<span class="
はじめに こんにちは、株式会社タイミーでプロダクトAIエンジニアとして働いている貝出です。直近は、タイミーの求人内容などのコンテンツモデレーションにLLMを利用した、システム開発や性能改善を行っています。 2026年3月9日(月)〜3月13日(金)に開催された「言語処理学会第32回年次大会(NLP2026)」に、今年は初めて現地参加しました。大会2日目は記録的な大雪に見舞われ、会場にたどり着くだけでひと苦労でしたが、それでも現地ならではの熱気は格別で、ポスター発表や他社エンジニアとの立ち話など、オンラインでは得られない学びが随所にありました。 NLP2026では多くの発表がありましたが、本記事ではLLMの評価・品質保証・安全性に関する発表に絞って紹介します。単に発表内容を紹介するだけでなく、実際のプロダクト開発や評価データ設計にどう接続できるかという観点で読み解きます。研究と実務をつなぐ視点として、評価設計やベンチマーク整備のヒントになれば幸いです。 大会2日目の大雪 言語処理学会年次大会について 会場内看板 anlp.jp 言語処理学会年次大会は言語処理学会が主催する学術会議であり、国内における言語処理の研究成果発表の場として最大規模のイベントです。 今年で第32回を迎え、発表件数は797件、最終日までの参加者数は2,316人と過去最大を記録しました。年々規模が拡大しており、NLP分野への関心の高さが伺えます。LLMの登場により一時は「研究することがなくなるのでは?」という懸念もあり、2023年には「ChatGPTで自然言語処理は終わるのか」というテーマでパネルディスカッションが行われたこともありました。しかしその懸念に反して、近年は「安全にLLMをどう使うか」「LLMの挙動をどう解釈するか」といった観点の研究が増えてきており、まだまだ研究題材は尽きない印象です。 なお、発表論文は言語処理学会のWebページで公開されているため、当日参加できなかった方でも閲覧可能です。 私自身も今回、社会人大学院での研究内容をもとにポスター発表を行いました。多くの方と議論でき、大変刺激になりました。合計90分間、ポスターの前で参加者に説明したり質問に答えたりと、途中で酸欠になりそうなほど白熱したセッションでしたが、ありがたいことにスポンサー賞としてレトリバ賞をいただくことができ、とても良い思い出になりました。 興味深かった発表 普段の業務では、「LLMを活用してビジネス課題をいかに解決するか」という問いと同時に、「LLMの出力をどう評価するか」「そのための評価データをどう設計するか」といった問題にも日々向き合っています。今回は、こうしたLLMの評価・品質保証・安全性というテーマを軸に、特に業務課題と関連の深かった4件の発表を取り上げます。 チュートリアル3:信頼できるAIへのソフトウェア工学からのアプローチ:「品質」技術の動向と課題 発表内容 本チュートリアルでは、ソフトウェア工学の観点から「信頼できるAI」の品質保証技術について解説されました。 まず、品質は「複数の特性から構成され、様々なニーズや要求を満たすこと」と定義されると説明されていました。また、品質には、対象システム自体に対して測るもの(例: レイテンシなど)と、実際にシステムを利用する段階で計測可能なもの(例: 顧客満足度など)の2種類が存在するとのことでしたした。そのうえで、価値やリスクはシステム全体で評価されるべきであり、AI部品ごとに適切に評価することの重要性が強調されていました。 AIの品質保証に関するガイドラインとしては、AIQMやQA4AIなどが紹介されました。これらのガイドラインでは、「AIパフォーマンス」「リスク回避性」「公平性」といった機械学習に特有の品質や、それを評価するための「被覆性(事例パターンが網羅的に含まれているか)」や「均一性(実際の母集団の分布に近いか)」などのデータセットにおける品質の重要性も整理されていました。 一方で、LLMの普及に伴い、入出力が非定型になってタスクの境界が曖昧になっています。また、正解が一意に決めづらくなったことで、評価・改善の難易度と工数が増大しているという現場課題も指摘されていました。LLMの手軽さからシステム開発自体は進めやすくなった反面、活動の重心は「開発」から「評価・改善」へと移行しています。しかし、「開発」と違って「評価・改善」では、工数換算をする意識が低くなりがちです。そのため、評価・改善の継続的サイクルを定着させることが困難だという課題が挙げられていました。 また、モデル評価の文脈としてソフトウェア工学における「自動テスト生成」の手法が紹介されました。代表的なものの一つが、テスト生成を最適化問題に帰着させてメタヒューリスティックに解く Search-Based Testing(探索的テスト) です。たとえば自動運転の分野では、この手法を用いることで事故が起きやすい弱点領域を探索したり、モデルの性能限界の境界を可視化したりすることが可能になっています。 最後に、言語モデルが今後ロボットや自動運転など物理世界にも応用されていく中で、よりリスクベースの評価が必要になるという展望が示されました。 感想 「開発」から「評価・改善」にエンジニアの工数の主なタスクが移り変わっているというところも、たしかになと思わずうなずいてしまいました。今後は「モデル開発」よりも、どう評価するか、どうデータセットを作るのかにML/AIエンジニアの重心が移るのかもしれません。 また、Search-Based Testingは初めて聞いたのですが、LLM審査のコンテキストに当てはめると、微妙な偽陽性・偽陰性を生む「境界線にある言い回し」を自動探索し、モデルやプロンプトの弱点を事前に洗い出す、といった使い方ができそうだと感じました。 [B2-1] chakoshi Fine: 多層防御に基づくLLM向けガードレールの設計と実装および評価 発表内容 本研究は、生成AIの安全な業務利用のためのガードレール構築に関するものです。前年のNLP2025で発表された chakoshi の発展系にあたります。 chakoshi では単一モデルに複数の役割を担わせていたため、あるリスクの検知精度を伸ばそうとすると別の精度が低下しやすいという構造的な制約が課題でした。本研究ではこの課題に対し、リスクごとに特化した5つの独立した防御機構を段階的かつ選択的に適用する多層アーキテクチャ chakoshi Fine を提案しています。複数のコンポーネントに分割したパイプライン構造にすることで、単一モデルでの全体最適化を避け、各ポリシーが専門性を高めつつ相互に弱点を補完する設計になっています。この結果、既存の商用ガードレールサービスと比較して高い検知精度を達成していました。 さらに、擬似業務タスクを通じて実際の業務を想定した有用性評価も行われています。ガードレール導入の有無が人間のタスク正答率や平均所要時間に統計的な差を与えなかったという結果が示されており、過剰検知によるユーザー体験の悪化や業務効率の低下を防ぎつつ、パスワード漏洩のような不正な入出力に対しては、98%の確率で遮断できていました。 感想 ガードレールを利用する際は、どうしても使用感が気になります。本研究が、検知精度だけでなく処理速度や「ユーザー体験を損なわないか」という点まで踏み込んで評価してくれているのは、実務側としてありがたいです。また、4B程度の軽量なLLMでもガードレールのスコープによっては、ある程度検知精度が担保できるという点も個人的には発見でした。 [Q4-3] LegalRikai: Open Benchmark - 法務ドメインの日本語ベンチマーク 発表内容 本研究は、実際の法務業務のワークフローを模した、法務ドメインにおける新たな日本語ベンチマーク LegalRikai を提案しています。 このデータセットは、弁護士の監修のもとで人手による精緻なアノテーションが行われており、高コストではあるものの高品質な内容となっています。法令改正の要約や指示に基づく契約書編集など、実際の法務業務を模した4つの複雑なタスクから構成されており、法務文書特有の長文インプットに対して構造化された出力を求める設計になっています。 評価においては、単一の指標ではなく、指示の遵守度・契約書全体の構造の一貫性・不要な変更の有無など、実務に即した複数の観点から評価する尺度が採用されています。正解データの作成から評価に至るまで専門家が深く関与しているため、データ数は各タスク25件と少数ながら厳選された内容です。さらに、評価者間の一致度(Cohen の κ スコア)を計測することで、アノテーションの妥当性やガイドラインの信頼性を担保しており、LLMの法務実務における実力を正確に測るための堅牢な基盤を提供しています。データセットは公開されており、論文内のリンクから参照可能です。 感想 「専門ドメインのベンチマークをどう設計するか」という観点で非常に参考になる研究でした。特に、評価観点を実務の複数軸に分解している設計や、少数でも質を担保するためにアノテーターの一致度を計測している点は、評価データを整備する際にも応用できそうです。「データ数は少なくても、専門家による厳密な設計で品質を担保する」というアプローチは、社内の評価データ構築においても積極的に取り入れたい考え方です。 [B8-13] 医療系対話AIにおける評価基準の策定と自動評価手法の比較検証 発表内容 本研究は、日本の医療事情に即した独自の評価データセットを構築し、医療系対話AIにおける「LLM-as-a-Judge」を用いた3つの自動評価手法を比較検証したものです。具体的には以下の3手法が比較されました。 総合評点方式:詳細なガイドラインに基づき1〜10点でスコア化 総合評点方式(簡易版):評価の観点のみを提示 項目別評価方式(チェックリスト形式):具体的な評価項目に対してTrue/False判定を行い加重スコア化 実験の結果、モデル間の全体的な性能差を識別する能力においては、意外にも詳細な指示を与えない「総合評点方式(簡易版)」が最も優れていることが分かりました。一方で、個別の会話に対する評価の「一貫性」や、医学的に危険な回答を確実に除外するといった「説明可能性・安全性」の観点では、「項目別評価方式」が最も優れていることが示されています。目的(モデル全体の性能比較か、個別回答の厳密な品質保証か)に応じて適切な評価アプローチを使い分ける重要性が裏付けられた研究です。 感想 「簡易版のほうがモデル間の性能差を検出しやすい」という結果は、直感に反していて面白かったです。評価指標によっては、どの形式の評価にするかを実施前に比較しておくといいのかもしれません。 「項目別評価のルーブリック設計には専門家のコストがかかる」という点は、スポンサーブースで他社のエンジニアと話していたときにも、全く同じ悩みとして挙がっていました。「評価の精度を上げたいが、設計コストをどこまでかけられるか」というトレードオフは、ドメインを問わず共通の課題なのだと改めて実感しました。スモールスタートする場合は「まず簡易版で全体傾向を把握し、問題が疑われる領域だけ項目別で深掘りする」という使い分けが現実的かもしれません。 おわりに 今回取り上げた4つの発表は、主に評価、評価データ、そして安全性に関するものでした。LLMの能力が飛躍的に向上した今、「人間の期待通りに生成できているのか」「安全にLLMを利用できているのか」という問いへの関心はますます高まっており、研究も着実に進んでいる印象です。 NLP2026では今回紹介しきれなかった魅力的な研究も数多くあり、この領域の裾野の広がりを実感しました。タイミーを安心・安全なプラットフォームとして維持するためのLLM活用について、多くの示唆を持ち帰ることができた大会でした。 We’re hiring! 現在、タイミーでは、データサイエンスやエンジニアリングの分野で、共に成長し、革新を推し進めてくれる新たなチームメンバーを積極的に探しています! product-recruit.timee.co.jp また、気軽な雰囲気でのカジュアル面談も随時行っておりますので、ぜひお気軽にエントリーしてください。↓ hrmos.co hrmos.co hrmos.co
福岡Rubyist会議05 参加レポート こんにちは!Timeeでバックエンドエンジニアをしている志賀(@akitoshiga)です。 表題の通り「福岡Rubyist会議05 」に参加してきたのでそちらのレポートを書きたいと思います! regional.rubykaigi.org 今回「Kaigi Pass」という社内制度を利用して参加しました。 「Kaigi Pass」とは、世界中で開催されているあらゆる技術カンファレンスへの参加を支援する制度です。 productpr.timee.co.jp 会場の様子 当日は福岡県福岡市博多区にある「リファレンス駅東ビル」というところで行われました。 会場いっぱいに来場者が集まりとても賑わっていました。 また、会場には福岡県八女市の名物である八女茶が提供されていました。 自分もいただいたのですがとても美味しかったです。 セッション 特に自分の関心が高かったセッションを3つほど紹介したいと思います。 SQLQL とは何だったのか 発表者 : yancya(@yancya)さん www.slideshare.net yancyaさんが取り組まれているSQLQLについての概要と、技術の変遷に伴ったアップデートのお話でした。 SQLQLとはWebクライアントからSQLクエリを送信して、その実行結果をJSONで返すというコンセプトです。 GraphQLのSQL版と考えるとイメージが掴みやすいと思います。 SQLQLに関しては以下で詳しく解説されています。 SQLQL #Rails - Qiita Client Challenge なお、ここではRDBMSにPostgresを使用することを前提としています。 SQLQLはクライアントが任意でSQLを送信できるので、これを安全に使えるようにするためにさまざまな工夫が施されていました。 WITH句によるCTEを使って取得対象のDBをラップすることでアクセスできる属性を絞り、秘匿すべきデータへのアクセスを制限しています。 INSERT, UPDATE, DELETEといった副作用を伴う操作に関しては自由に実行できないようにSELECTのみの権限しか実行ユーザーには与えず、定義した書き込み権限のあるストアドプロシージャでしか副作用のある操作を実行できないような仕組みを取られていました。 また、悪意のあるクエリの対策としてpg_queryによってクエリをパースしてAST(抽象構文木)をチェックしていました。 課題も存在していて、再帰処理にはうまく対応できないそうです。 SQL ServerやMySQLは再帰処理の深さを設定できるのですが、Postgresだと存在していないため代わりにタイムアウトのみで設定しているそうです。 クライアントでクエリをフェッチすることが可能になるので、これを用いたときにAPI開発コストの削減に繋がるのは良さそうだなと思いました。 ビジネスロジックがストアドプロシージャに集中してしまわないかなというのと、サーバー側ではクエリを効率化できないのでデータ量が多かったりリレーションの複雑なテーブルからデータを取得する場合はクライアント側で工夫が必要だなと感じました。 SQLをそのままパラメーターにしてWeb経由でクエリを投げるアイデアと、安全性を担保するためのさまざまな試みに技術者のロマンを感じました。 再帰処理に関してはPostgreSQLに存在するCYCLE句を使えば安全に扱えそうなのですが、そうすると特定のRDBMSに依存してしまうのと、クライアントとクエリの決め打ちをしなければならずコンセプトと乖離しそうな気がするので悩みどころだなと感じました。 今回はこのSQLQLのアップデートとしてWAL監視のアイデアを取り込んだデモアプリを披露されていました。 WAL(先行書き込みログ)とはデータベースに変更を行う前に操作内容を記録するログのことであり、このWALを監視することでリアルタイムなデータストリームの観測が可能で、このアイデアをSQLQLに応用されていました。 WAL監視については自分は初見だったのですが、CDC(Change Data Capture)の実装に利用されたりしているそうです。e.g. Debezium Server このほかにもSQL標準の変遷やLive QueryなどSQLQLを起点としてDB 、データ基盤についての幅広いお話を伺いました。 Live Queryで話に上がっていたKafka Streamsについては内部動作と構造に興味が湧いたので後日その深掘りをしてみました。 また、WAL監視については今後複数コンポーネント間でリアルタイムにデータ更新を検知したいときなどにこのアイデアが役立ちそうだなと思いました。 型を書かないRuby開発への挑戦 発表者 : shia(@riseshia)さん speakerdeck.com 自作GemのTypeGuessrのお話。 TypeGuessrは「型情報を開発者が追加せずに型情報を得る」ことをコンセプトに開発されたGemで、Ruby LSPのアドオンという形で使用します。 github.com Rubyに型情報をもたらすツールはいろいろありますが、SteepやSorbetといったような型定義を行い正確な型情報を得るものとは明確に棲み分ける形で開発されています。 Hash/Arrayに対してStructural Typing(構造的部分型)をサポートしつつも複雑な型推論が走りそうな場合はあえてuntypedにして計算量をコントロールしています。 特徴として、Duck Typingに基づくヒューリスティックな推論を用いて型情報を取得しており、クラスに定義されたメソッドをそのレシーバーから辿ることによってこれを実現しています。 この方法でも行数が10万行以上のRailsプロジェクトであれば平均10%〜20%で型情報を得られるそうです。 Duck Typingを利用して振る舞いから型を推論する部分はRubyらしさを感じるとともにユニークで興味深いなと思いました。 まだできたばかりでパフォーマンスには向上の余地があるそうで、このアプローチでどのようにこれらを解決していくのか動向を追ってみたいなと思いました。 少し話は逸れますが、型検査ツールのパフォーマンス改善という話でふと去年の関西Ruby会議で聞いたpockeさんのこのキーノートを思い出しました。 speakerdeck.com Steepのメモリ削減のために自作のプロファイラで観測してプロセス間通信のレベルまで踏み込んで改善に取り組んだ過程がとても面白かったので、よかったらこちらもチェックしてみてください。 Ecosystem on parse.y 発表 : S.H.さん S.H.さんが開発されているparse.yを利用したGemであるkanayagoとigata、そしてこれらを組み合わせたエコシステムのお話 parse.yとはRubyの文法定義ファイルのことで、昨今のRubyist界隈を取り巻くパーサームーブメントを語る上で欠かせないものです。 parse.yはRubyコミッターのydahさんの以下のスライドがparse.y周辺の情報やパーサー自体についても丁寧に解説されていて理解しやすいです たのしいparse.y - Speaker Deck S.Hさんはこのparse.yを利用して、パースしたAST(抽象構文木)ノードをRubyクラスとして扱うことができるkanayagoを開発されました。 github.com ASTをRubyオブジェクトにすることで従来よりももっと手軽にASTを扱えるようになり、パターンマッチングにも対応可能になっています。 これによってコード解析・構文チェックなどといったRubyの文法のASTに関する操作がとても直感的・簡単に行えるようになっています。 またS.Hさんはこのkanayagoをベースとしてigataとkanayago-lspを開発されました。 github.com igataはkanayagoが生成するRubyクラス名、メソッド名、引数の情報などを抽出してMinitestやRSpecに対応したテストファイルを自動作成します。 これに加えてLLMと組み合わせて、テストの中身まで自動補完させる運用も想定されています。 kanayago-lspはkanayagoを用いてVSCodeやVimなどで利用でき、Rubyの新しいパーサーであるPrismでは検知できないものも検知できるそうです。 S.Hさんはこのparse.y、これを利用したkanayagoを利用したエコシステムの構築を目指しており今後はLinterの開発を目指しているそうです。 S.HさんのASTに使われる各ノードを体系立った独自のRubyクラス群にラップするというアイデアがとても素晴らしいなと思いました。 parse.yから生成できるノードは100種類以上あるのでかなり根気がいる作業だと思いましたが、ここは生成AIをうまく活用されたそうです。 Ruby3.4からデフォルトパーサーがparse.yから生成されるパーサーからPrismに置き換わりましたがparse.yの根強い人気というか盛り上がりを感じました。 先ほど紹介したTypeGuessrもそうなのですが、何かを作るにあたりよりRubyらしさを追求するアプローチをみなさんされていて、このマインドはRubyistに通じるものなのかなと感じていました。 これらは開発のお手伝いをしてくれる方を絶賛募集中とのことです。自分もとても興味があるので機会があればパッチを投げたいなと思いました。 そのためにkanayago自体も積極的に使ってみたいと思います。 これらの他にもこの日の