Timee Product Team Blog

タイミー開発者ブログ

Kotlin Fest 2025に参加してきました!

こんにちは、タイミーでAndroidエンジニアをしている ふなち(@_hunachi)です 😆

タイミーの Kaigi Pass という制度を使い、Kotlin Fest 2025 に参加してきたので、その感想などを紹介します!

ちなみに、弊社からは @tick_taku と私の2名で参加しました。

聞いたセッション紹介

@tick_taku と 私、それぞれが特に印象に残ったセッションをご紹介します!

tick_taku

「動く」サンプルでスムーズなコミュニケーションを 〜CMP時代のKotlinPlayground活用最前線〜

2025.kotlinfest.dev

KotlinPlayground のプラットフォームに Compose Multiplatform が選択できるため、Web 上でサクッと画面を構築して URL を共有することで動くものベースにチームコミュニケーションを活性化しよう、というセッションです。

KotlinPlayground は Kotlin 勉強し始めのころに「このコードはどういう動きをするのか?」を確認するために利用したことはありましたが、まさか UI を共有することができるようになっているとは...明日から使ってみたい tips な内容でした!

自分は Android アプリエンジニアなのでさっそく Android 向けの UI を構築して共有したいなと思いました。ですが実際触ってみると activity package は import できそうになかったので、基本は Web 向けで Android アプリ的にはコンポーネント単位の挙動の確認などに利用できるのかなと感じました。

またWeb上の環境なのでプロダクトコードをそのまま載せるのはやめておいた方が無難かもしれません。

こちらのセッションで Firebase Studio なる存在を初めて聞ききました。AI による vibe coding をベースとしたノーコード開発向けのプラットフォームでしょうか。

UI 共有に利用するだけだとオーバースペック気味そうですが、テキストからモックを作らせてコミュニケーションを図るという目的であれば有用そうですね。

フルKotlinで作る!MCPサーバー、AIエージェント、UIまで一気通貫したAIエージェントシステム

2025.kotlinfest.dev

もともと Kotlin で MCP サーバー作れないかな〜と思っていたところに Koog による AI エージェント作成までを紹介されていて、フルスタック Kotlin の可能性を見せていただき、とてもワクワクしました。やはり Kotlin は素晴らしい言語!!

チャットのチェックポイントにおけるハマったポイントなど、経験者の少ないフレームワークの実体験に基づくナレッジの共有はとても貴重でありがたいです。

公式 SDK が Streamable HTTP をサポートしていないというのは MCP サーバーを作成する上でネックになりそうですね。

このセッションを聞いた後に上記の KotlinPlayground のセッションを聞いていて思ったのですが、LLM を利用して仕様書や要点から KotlinPlayground 使ってモックを作らせて短縮リンク発行するエージェント作れないかな〜🤔

アイデアを話してまとめているだけで動作が見られる簡単なモックができ、よりプロダクトのコミュニケーションを円滑にできるのではと期待値が高まりました。

とは言え、 Firebase Studio が想像している通りであれば、用途が被りそうなので情報を集めていきたいです。

内部実装から理解するCoroutines ー Continuation・Structured Concurrency・Dispatcher

2025.kotlinfest.dev

普段何気なく利用している Coroutines の詳細な内部処理をコードと図解を用いて詳細に解説していてとても勉強になりました。

実際この辺りの内部仕様を把握していなくてもなんとなくで使えてしまい非常に便利ですが、ディテールを理解することでより深く・効率的に使いこなせるようになるのだと実感しました。

少しハードルの高いデコンパイルやライブラリのソースコードを読んでみることに挑戦しようと思える素晴らしいセッションだと思います。

余談ですが解説記事が事前に公開されており、進行に合わせて読み進めながらセッションに集中できたこともとても良い体験でした。ありがとうございます!

ふなち

Kotlinを支える技術:言語設計と縁の下の力持ち

2025.kotlinfest.dev

このセッションでは、Kotlinの言語設計の裏側と、この一年でKotlinがどのように進化してきたのかについて深く知ることができました。

言語設計に関してはCompanion objectの話を聞くことができました。

KotlinのCompanion objectは、その使用の95%がJavaでいうstaticを宣言する場として使われています。しかし、実際にはClass.Companionというを生成しており柔軟な使い方ができる点や、クラスに一つしか作れない点などの問題があるそうです。

この問題を解決するため、過去にはnamespacestaticなどさまざまなプロポーザルが検討されましたが、Companion objectとの併用時の課題などから、全てリジェクトされてしまったそうです。しかし、現在はcompanion 構文を使えるようにすることで、これらの課題を解決しようとしているという話でした。

また、この話の中で「一度リリースしてしまうと、それは本や動画、ネット上の記事として末長く残ってしまう。だから、簡単にDeprecatedにはできない。新しい機能を作る際には、とても慎重にならざるを得ない。」とおっしゃっていたのが特に印象に残りました。

他にもセッション内では、Kotlin 2.2や2.3、そしてAndroid Studioのアップデートについても触れられており、Kotlinは更に年々便利になっているなと改めて実感しました。

また、Kotlinのロードマップが年に2回ほど更新されているとのことだったため、Kotlin Fest の数日後にAndroidのメンバー全員で、最新のロードマップを確認する時間を作りました。Kotlin Notebookの開発が進んでいることなどを知れて、とても有意義な時間となりました。半年後にも、またメンバー全員で読もうと思います!

せめて、ネイティブらしく - マルチプラットフォームと撤退戦略

2025.kotlinfest.dev

KMP(Kotlin Multiplatform)をあまり触ったことがない自分としては、「KMPを導入した場合の欠点」や「万が一、撤退する場合にどうすべきか?」という点が気になり、このセッションを聞きに行きました。

KMPをほぼ触ったことがないのですが、このセッションは主にiOSアプリ開発を行う際の内容だったため、FlutterやAndroidを触っている自分にとって、比較的分かりやすい内容でした。

KMP iOSのStableリリースもあり、KMPでのiOSアプリ開発はどんどんしやすくなっていることや、KMPでは実現が難しいこともKotlin/Nativeで頑張ればほとんど実現できると知れ、KMP導入のハードルはかなり下がっているんだなと感じました。

「撤退戦略」に関しても、実装時にレイヤーを分けるといった具体的なTipsが紹介されており、とても勉強になりました。

Rewind & Replay: Kotlin 2.2 が変えるCoroutine デバッグ最前線

2025.kotlinfest.dev

最近はCoroutinesの深いデバッグをする機会が減っていましたが、このセッションでCoroutinesのデバッグがこんなにも進化していることを知ることができました。

ただ、新しいデバッグ機能をAndroid Studioではまだ使えないそうなので、早くAndroid Studioでも対応してほしいなと思いました😢

一緒に紹介されていたstacktrace-decoroutinatorというライブラリは、Android Studioでも使用可能とのことだったので、いざという時に頼らせてもらおうと思います!

KoogではじめるAIエージェント開発

2025.kotlinfest.dev

現在のAI Agent開発の状況や、Koog がいかに便利かを知ることができました。

カレンダーに予定を追加してくれるようなAgentも作れるという実例を見て、これは社内ツールや外部サービスとの連携など、色々な用途で使えそうだと感じました。

細かな実装のコツも色々紹介されており、Koogを使って、社内・社外問わず、AIエージェント開発にチャレンジしてみたいというモチベーションが高まりました!

全体を通して

全体的な雰囲気は、セッションもブースもたくさんあり、賑わっていて楽しかったです。

お弁当やPCを持ってきていた関係で荷物が多かったため、クロークがあったのも本当に助かりました!

懇談会では、サーバーサイドでKotlinを使っている企業の方ともお話ができたり、Kotlin Fest ならではの交流ができていい刺激になりました!弊社のサーバーサイドもKotlinになればいいのに…(小声)🤫

Kotlin Fest で学んだことや得られたモチベーションを活かして、明日からの開発に繋げていきたいと思います!

推しのあすけんのお姉さんとのツーショに喜ぶ tick_taku

「進捗を更新して」で進捗管理が終わる世界 〜LLMとの協働で変わったプロジェクト運用

こんにちは。タイミーでデータサイエンティストをしている吉川です。

最近、生成AIを使ったプロジェクト管理の仕組みを試しているのですが、想像以上に働き方が変わったので、その体験を共有したいと思います。

TL;DR

  • 「進捗を更新して」の一言で、5つの管理ファイルが自動更新される仕組みを作った
  • 成果物作成時間が約50%削減(6.5時間→3.25時間)※体感ベース・タスクにより削減率は異なる
  • LLMが「外部ツール」から「チームメンバー」に変わる感覚
  • 秘訣は、Git管理されたMarkdownファイルにドキュメントを集約し、自動化ルールを作成すること

はじめに:もっと本質的な仕事に時間を使いたかった

プロジェクト管理をしていて、こんなふうに感じたことはありませんか?

デイリースクラム準備
  - タスク管理ツールを開く
  - 「昨日のタスク、進捗率どうなった?」
  - 完了タスクを目視でカウント(1, 2, 3...)
  - 電卓で進捗計算「40/45...88.9%か」
  - 手動で更新

今日のタスクを決める
  - 「タスクAとB、どっちを先にやるべき?」
  - 依存関係を確認しようとする
  - 複数のツールを参照して判断(15分)

タスク決定、作業開始
  - 「前提となる仕様、どこだっけ?」
  - 「前に決めた内容、何だっけ?」
  - 複数のツールやドキュメントを探索(30分)

文書を書き始める
  - 構造を考え、内容を練り上げる(4時間)

週次報告の準備(金曜日)
  - 完了タスクを手作業でカウント
  - Sprint切り替え準備:未完了タスクを整理
  - 次週の準備(30分)

日常的な進捗管理や情報収集に時間を使うより、もっと創造的で本質的な仕事に時間を使いたい。そう考えるようになりました。

やったこと:Git + Markdown + LLM自動化ルールで進捗管理を自動化

そこで、以下のような仕組みを作りました。

1. すべてのドキュメントをGit管理されたMarkdownファイルに集約

プロジェクトに関するドキュメントをすべてMarkdown形式でGitリポジトリに格納しました。

requirements/
├── A_現状分析/(5ファイル)
│   ├── p01_a_01_high_level_kpi_analysis.md
│   └── ...
├── B_詳細分析/(5ファイル)
├── C_ビジネス要件/(5ファイル)
├── D_データ要件/(5ファイル)
├── F_機能要件/(4ファイル)
├── S_詳細設計/(7ファイル)
└── execution_management/
    ├── sprint_plans/sprint6.md
    ├── phase1_issues.md
    ├── project_epics.md
    ├── project_dashboard.md
    └── project_roadmap.md

なぜMarkdownなのか?

  • ファイルベースなので、LLMがコンテキストを取得しやすい
  • 相対リンクで、ファイル間の関連性をLLMが自動理解できる
  • Git管理により、変更履歴を追跡できる
  • grepによる高速全文検索が可能

2. 「進捗を更新して」というトリガーワードで自動処理

次に、Cursor(AIエディタ)のルール機能を使って、自動化フローを定義しました。

なぜLLMなのか?

  • Git管理のMarkdownに集約された全体の文脈を横断的に理解できる
  • 関連ドキュメントを自動収集し、依存関係を把握して不足情報だけ質問できる
  • 叩き台の生成と整合性検証を自動化し、人はLLMと壁打ちしながら仕上げに集中できる

「進捗を更新して」と入力すると、以下の処理が自動実行されます:

実際の動作例

※以下は実際の出力を読みやすく簡略化したものです。

私: 進捗を更新して

Claude:
╔══════════════════════════════════════════════════════╗
║  📊 進捗更新の自動処理を開始
╚══════════════════════════════════════════════════════╝

┌──────────────────────────────────────────────────┐
│ 🗂️ ステップ1: エビデンス確認結果
├──────────────────────────────────────────────────┤
│  A.現状分析(5個全完了)
│   ├─ p01_a_01_high_level_kpi_analysis.md  ✅
│   ├─ p01_a_02_stakeholder_hearing_summary.md  ✅
│   ...
│
│  D.データ要件(1個)
│   └─ p01_d_01_data_sources_list.md  ✅
└──────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────┐
│ 📈 ステップ2: 進捗率算出
├──────────────────────────────────────────────────┤
│  完了Sub-issue数: 17 → 18(+1)
│  全Sub-issue数: 54
│
│  進捗率 = (18 / 54) × 100 = 33.3%
│  進捗バー: ███░░░░░░░ 33.3%
└──────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────┐
│ 📝 ステップ3: 5ファイル同時更新
├──────────────────────────────────────────────────┤
│  1️⃣ sprint6.md  ✅ 更新完了
│  2️⃣ phase1_issues.md  ✅ 更新完了
│  3️⃣ project_epics.md  ✅ 更新完了
│  4️⃣ project_dashboard.md  ✅ 更新完了
│  5️⃣ project_roadmap.md  ✅ 更新完了
└──────────────────────────────────────────────────┘

✅ 進捗更新処理が完了しました

3. エビデンスベース管理

進捗の判定は「実ファイルが真実」という哲学に基づいています。

そのため、あらかじめ生成される成果物のファイル名や置き場所などを決めておく必要があります。

タスク一覧:
- A-1: API設計書 → ファイルあり、ただし [WIP] タグ付き
- A-2: DB設計書 → ファイルあり ✓
- A-3: 画面設計書 → ファイルあり ✓
- A-4: テスト計画書 → ファイルあり ✓
- A-5: 運用手順書 → ファイルなし(未着手)

LLMの判定:「WIPは除外、未着手1個、実際は60%完了」
→ 進捗率 = 完了数(3) ÷ 全体数(5) × 100 = 60%
→ 成果物ベースの進捗把握で進捗率を明確化

推測や自己申告を排除し、実成果物ファイルの存在で作業完了を判定します。

効果:体感で成果物作成時間が50%削減、そして仕事の質が変わった

Before(従来の方法)

10:45 要件定義を開始
  - 「前提となる仕様、どこだっけ?」
  - 「前に決めた内容、何だっけ?」
  - 複数のツールやドキュメントを確認(30分)

11:15 材料が揃って、ゼロから文書を書き始める
  - 構造を考えながら、内容を練り上げる(4時間)

15:15 レビュー依頼
  - レビュー指摘を受けて、修正対応

17:15 初稿完成(合計6.5時間)

After(LLMとの協働)

11:00 「タスクCに取り組んで」と指示

11:05 LLMがタスクの本質を理解・必要情報を一覧化(5分)
  - 「このタスクの目的は〇〇ですね」
  - 「必要な情報:A, B, C。不足:Dを教えてください」

11:10 不足情報を提供(20分)

11:30 LLMが叩き台作成(5分)
  - 関連ドキュメント自動収集済み
  - 7割完成の初稿を生成

11:35 LLMと壁打ちしながらじっくり詰めていく(2時間30分)
  - 私:「UIの表示項目これで全部?」
  - LLM:「〇〇の観点が抜けています。追加しましょうか?」

  - 私:「エラーハンドリングのパターンは?」
  - LLM:「A, B, Cの3パターン。それぞれメリット・デメリットは...」

14:05 最終調整(10分)

14:15 高品質な成果物が完成!

Before: 6.5時間 After: 3.25時間 - 50%削減、しかも品質向上 !

体感的に変わったこと

指標 Before After 変化
進捗更新作業 手動で5分~30分 LLM作業10分~30分+人の確認1分~5分 50%削減
成果物作成 人10割 LLM叩き台5~7割+人仕上げ3~5割 50%削減
視点の網羅性 人の経験に依存 多角的な視点で抜け漏れ減 抜け漏れ減

※ 上記の50%削減は体感ベースであり、タスクの性質によって削減率は変動します。

削減率が高かったタスク(60-80%削減)

  • 一般的な知識で構成されるタスク
  • テンプレート化・パターン化しやすい
  • LLMの事前学習データに豊富な事例がある
  • 例:技術調査、API設計書作成、一般的なテスト計画書

削減率が低かったタスク(20-40%削減)

  • 組織固有の知識が必要なタスク
  • LLMに与えるコンテキストが膨大
  • 人間の判断・確認が必要
  • 例:既存システムの設計意図の理解、複雑なビジネスロジックの要件定義

その他の副次効果

Markdown集約による「組織の記憶」は、進捗管理と成果物作成以外にも、様々な場面で価値を発揮します。

1. コンテキストを渡さずに、即座に壁打ちができる

※以下は実際の出力を読みやすく簡略化したものです。

私: 機能Xのユーザー認証、どう実装すればいい?

Claude:
S-1で決定した認証方式を使用してください

【認証方式】
- JWT + OAuth 2.0(Google認証)
- トークン有効期限:24時間

【実装制約】
- 共通ライブラリ:@/lib/auth.ts を使用
- エラーハンドリング:共通形式(S-7:ログ・エラー設計)

【依存関係】
- ログイン機能:完了済み
- API仕様:S-3(API設計)に記載

LLMが過去の意思決定(S-1で決定した認証方式)を記憶しているので、すぐに実装方針がわかります。

2. 属人化の排除

「組織の記憶」があることで、特定メンバーへの依存が最小になります。

※以下は実際の出力を読みやすく簡略化したものです。

私: 担当メンバーが突然退職することになった。
    引き継ぐため機能Xの実装状況を把握したい。

Claude:
機能X(ユーザー認証)の進捗状況

【完了したIssue】
✅ N-1: セキュリティ基盤設計(100%完了)
   - Cloud IAP + NextAuth.js設計
   - 決定日: 2025-09-15(CTO承認済み)

【次のIssue】
🟡 N-2: ユーザー認証機能実装(進捗 60%)
   ✅ 完了: LoginForm基本実装
   ⏳ 残タスク: エラーハンドリング実装

従来では、担当者のアサイン変更時に情報の引き継ぎに時間がかかっていました。

LLMによる組織の記憶があれば、即座に状況を把握し、スムーズに作業を引き継げます。

3. 思考の深まり(LLMとの壁打ち)

  • 下準備(情報収集・構造化)をLLMに任せることで、本質的な思考に集中できます
  • LLMと壁打ちすることで多角的な視点を獲得できます(要件の漏れ、エラーハンドリング、セキュリティ等)
  • 一人では気づかなかった観点をLLMが補完してくれます
  • 結果:最大の価値は時間削減ではなく品質向上にあります

運用してわかったこと

  • 始めるのは簡単だが、期待通りに動かすにはそれなりの試行錯誤が必要でした
  • プロンプトの調整、ルールの修正を何度も繰り返す必要がある
  • しかし、一度作れば継続的に価値を生み出し続ける
  • 長期的な投資対効果が初期の手間を上回る

まとめ

この記事では、「進捗を更新して」で進捗管理が自動化され、LLMとの壁打ちで成果物作成が効率化される仕組みを紹介しました。

実現の基盤となる3つのポイント

1. Git管理のMarkdownに集約

  • LLMが「組織の記憶」として機能
  • 関連ドキュメントを自動収集・整理
  • 進捗管理と成果物作成の両方を支える基盤

2. 自動化ルール(トリガーワード)

  • 「進捗を更新して」で5ファイル同時更新
  • Sprint期限超過の自動検出

3. エビデンスベース管理

  • 実成果物ファイルの存在で進捗を判定
  • 推測や自己申告を排除

得られた効果

  • 事務作業の負荷が半減し、品質は安定化
  • 創造的な仕事に時間を使え、アウトプットの質が向上
  • LLMは「外部のツール」から「内部のチームメンバー」に変化

最後までお読みいただき、ありがとうございました!

LLMアプリケーション向けProduction Readiness Checklistの作成

MLOpsエンジニアのtomoppiです。

データエンジニアリング部 データサイエンスグループ(以下、DS G)に所属し、ML/LLM基盤の構築・改善に取り組んでいます。

概要

2025年4月、タイミーPlatform EngineerのMoneyForestさんが、「タイミーにおけるProduction Readiness Checkの取り組み」という記事を公開しました。サブシステムや新規サービスのリリースに際しての評価基準を定めたもので、MLOpsとしても参考になる部分が非常に多くありました。

その記事に触発され、DS Gとしても再現性高くLLM Applicationを構築・運用するための評価基準を定めたいと思うようになり、本記事で言及する Production Readiness Checklist for LLM Applicationの策定に至りました。

背景

2024年以降、DS Gでは複数のLLMを活用したプロダクト開発に取り組んできました。しかし、前述のチェックリストをDS Gが構築・運用する LLM Applicationに適用しようとすると、以下のような課題に直面しました。

  1. AWS前提で書かれているため、DS Gで利用しているGoogle Cloud用に読み替える必要がある
  2. LLM特有の非決定性への考慮が必要
  3. 継続的評価やGenerative AI ライフサイクルの観点が不足している

チェックリスト策定の方針

技術に依存しない普遍的な原則と、タイミーDS Gでの具体的な実装に基づいたガイドの2部構成としました。

理由としては、現在はCloud Runをベースとした運用となっていますが、将来的にGKEの採用やECSへの移行などが十分に可能性としてあるためです。

また、RAG、Agentic Workflow、tool useなどのより高度なLLM利用は対象外としました。

それらを利用するアプリケーション設計・構築の際は、本記事で紹介するチェックリストを土台とし、新たにより専門性の高いチェックリストやそれに準ずる評価基準を設ける想定です。

ビジネス目標に関してはスコープアウトすることも考えましたが、ROIは大事にしていきたいというDS Gの意思として入れ込むことにしました。

チェックリスト

0. 戦略的目標とビジネスアライメント

LLM導入の目的と期待される成果を明確にします。

0-1. ビジネス目標の明確化

  • [ ] 測定可能なビジネスゴール(コスト削減率、顧客満足度向上、処理時間短縮等)が設定されている
  • [ ] ユースケースに対する期待される精度・応答速度が定義されている

0-2. 成功指標(KPI)の設定

  • [ ] ユースケース固有のKPIが定義されている
  • [ ] KPIの測定方法とダッシュボードが整備されている

1. 安定性・信頼性

システムを再現可能かつ自動化された方法でデプロイ・運用できるようにします。

1-1. 構成管理

  • [ ] すべてのコードがバージョン管理システムで管理されている
  • [ ] プロンプト(システムプロンプト、テンプレート等)がバージョン管理されており、変更履歴が追跡可能(監査可能)な状態になっている

1-2. CI/CD

  • [ ] Lint、単体テスト、セキュリティスキャン(静的解析)がCIパイプラインで自動化されている
  • [ ] 開発(dev)、ステージング(stg)、本番(prod)環境へのデプロイがCDパイプラインで自動化されている

1-3. リリースプロセス

  • [ ] プロンプトやモデルの変更が、ステージング環境で品質評価を実行した後に本番にデプロイされるプロセスになっている
  • [ ] カナリアリリースや段階的ロールアウトで、主要メトリクス(エラーレート、精度、コスト)を監視しながらリリースされる仕組みが確立している

1-4. LLM選定と継続性

  • [ ] 利用モデルのSLA/SLOを踏まえたフォールバック戦略が定義されている
    • プライマリLLM APIが利用不可時のフォールバック先(別モデル/静的レスポンス/エラー表示)
    • リトライポリシー(回数、待機時間、指数バックオフ等)
    • タイムアウト設定
  • [ ] モデル非推奨・廃止のスケジュールを把握しており、利用不可能になる前にモデルを更新するプロセスが確立している

2. スケーラビリティとパフォーマンス

トラフィックの増減に対応し、効率的なリソース利用を目指します。

2-1. キャパシティプランニング

  • [ ] コンテナ実行環境でオートスケーリングが設定されている
  • [ ] 利用するLLM APIプロバイダーのレート制限(TPM: Tokens Per Minute / RPM: Requests Per Minute)を把握し、自システムのキャパシティプランに反映されている
    • プロバイダー側の制限値を文書化
    • 制限値を超えないための流量制御(レートリミッター)の実装

2-2. トラフィック・トークン管理

  • [ ] ビジネス要求の変化に伴うトラフィック増加とその影響について、ステークホルダーと認識を揃えている
  • [ ] リリース時点で必要なスループットと、システムの最大許容スループットを算出している
  • [ ] 1セッションあたりの消費トークン数の見積もりを算出している
    • 入力トークン数(プロンプト + ユーザー入力 + コンテキスト)
    • 出力トークン数(予想される生成テキスト長)

3. 耐障害性と大惨事対応

システムの一部が故障しても、サービス全体が停止しないようにします。

3-1. 障害シナリオ

  • [ ] 想定される障害シナリオが洗い出され、文書化されている
    • LLM API障害(タイムアウト、5xx エラー、レート制限超過)
    • 依存サービス障害(データベース、外部APIなど)
    • ネットワーク障害
    • リソース枯渇(メモリ、CPU、ディスク)
  • [ ] 各障害シナリオに対応したRunbook(対応手順書)が作成されている
  • [ ] 障害発生時の影響(ビジネス損失、ユーザー影響等)を見積もっている
  • [ ] LLM API起因による長時間の回復困難な障害が発生した場合の対応方針についてステークホルダーと合意されている

3-2. LLM APIの可用性

  • [ ] システム要求(即時性、UX等)とLLM APIの可用性を踏まえたLLM処理コンポーネントの呼び出し方式(同期/非同期)が選択され、システムアーキテクチャに反映されている。
  • [ ] LLM API障害時のフォールバック・リトライ戦略が実装されている
    • エラー種別ごとのリトライ可否判定(429はリトライ、4xxの多くはリトライ不可等)
    • Exponential Backoffによるリトライ間隔の調整
    • Circuit Breakerパターンの導入(連続失敗時に一時的にリクエストを停止)
  • [ ] LLM APIの冗長化が検討され、必要に応じて実装されている
    • 複数のLLMプロバイダーまたは複数のモデルを利用可能にする
    • フェイルオーバーの仕組みを実装

3-3. 回復性テスト

  • [ ] 負荷テストを実施し、想定トラフィック下での挙動を確認している
  • [ ] 主要な障害シナリオを再現させた際、その障害が検知・アラートされることを確認している(カオステスト)

4. 安全性

LLMが生成する有害なコンテンツや不適切な振る舞いを防ぎます。

4-1. リスク分類とインシデント対応

  • [ ] ユースケースに合わせた安全性リスク分類が定義されている
    • 例: 誤情報、バイアス、プライバシー侵害、非倫理的なアドバイス、有害コンテンツ(ヘイトスピーチ、暴力的表現等)
  • [ ] 安全性に関するインシデント発生時の対応プロセス(Runbook)が定義されている
    • インシデントの検知方法
    • エスカレーションフロー
    • 緊急時の対応(プロンプトの切り戻し、機能の一時停止等)

4-2. ガードレール

  • [ ] 安全性リスク分類がガードレールのルールに反映されている
  • [ ] 入力ガードレールが実装されており、以下を検知・ブロックできる
    • プロンプトインジェクション攻撃
    • 不適切なトピック(暴力、ヘイト、性的コンテンツ等)
    • 機密情報(PII等)を含む入力
  • [ ] 出力ガードレールが実装されており、モデルが生成した以下のコンテンツをユーザーに届ける前に検知・フィルタリングできる
    • 有害コンテンツ(ヘイトスピーチ、暴力的表現等)
    • 機密情報(PII、APIキー等)
    • 明らかなハルシネーション(事実と異なる情報)
  • [ ] ガードレールで検知された違反はすべて記録されている

4-3. Red Teaming

  • [ ] 定期的なレッドチーミング(敵対的テスト)が計画・実行されており、新たな脆弱性を継続的に探索するプロセスが確立している
    • ジェイルブレイク(システム制約の回避)
    • 巧妙なプロンプトインジェクション
    • 複数ターンにわたる対話での安全性回避

5. 監視

システムの状態を可視化し、問題に迅速に対応できるようにします。

5-1. アプリケーションロギング・トレーシング

  • [ ] アプリケーションログが構造化ログ(JSON等)で出力されている
  • [ ] リクエストごとに一意のIDが生成され、ログとトレースに出力されている
    • 分散トレーシング対応(トレースID、スパンIDの伝播)
    • 上流サービスから受け取ったIDを継承
  • [ ] APM(Application Performance Monitoring)ツールでエンドツーエンドのトレースが可能になっている

5-2. 可視化とアラート

  • [ ] 主要メトリクスを一覧できるダッシュボードが整備されている
    • システムメトリクス: CPU、メモリ、リクエスト数、レイテンシ
    • ビジネスメトリクス: 利用回数、成功率、ユーザー満足度
    • LLM固有メトリクス: トークン消費量、API利用料金、エラーレート
  • [ ] サービスレベル指標(SLI)と目標(SLO)が定義されている
    • 例: 可用性 99.9%、P95 レイテンシ < 3 秒、エラーレート < 1%
  • [ ] SLO違反やシステム異常(エラーレート急増やリソース逼迫)時にアラートが発報される
  • [ ] LLMガードレール違反検知数や検知率をダッシュボードで確認できる
  • [ ] LLMガードレールにより検知された違反を重大度に応じてアラート通知する仕組みが確立している

5-3. LLM Observability

  • [ ] LLM APIへのリクエストが分散トレーシングシステムと統合されており、同一リクエスト内のLLM呼び出しがスパンとして関連づけられている
  • [ ] LLM APIへのリクエスト単位で以下の情報がトレース可能になっている
    • 入力プロンプト(機密情報をマスキング済み)
    • 出力レスポンス(機密情報をマスキング済み)
    • 利用モデルとパラメータ(temperature、max_tokens等)
    • レイテンシ(TTFB: Time To First Byte、全体レスポンス時間)
    • 消費トークン数(入力/出力)
    • 概算コスト
  • [ ] トークン消費量とコストの急増を検知するアラートが設定されている

6. 品質保証(QA)と評価プロセス

LLMの出力品質と安定性を客観的に担保します。

6-1. オフライン評価セット

  • [ ] LLM出力を評価するためのデータセット(ゴールデンセット)が定義・管理されている
    • 代表的なユースケースをカバーする入力と期待される出力のペア
    • データセットの保存場所と管理方法が明確
  • [ ] エッジケース、既知の失敗パターン、敵対的入力を評価するデータセットが定義・管理されている

6-2. オフライン評価指標

  • [ ] タスクの目的に沿った具体的な評価指標が定義されている
    • 分類タスク: Accuracy、Precision、Recall、F1-score
    • 生成タスク: BLEU、ROUGE、人手評価(流暢性、正確性、関連性)
    • 安全性: 有害コンテンツ検出率、PII漏洩率

6-3. オンライン評価

  • [ ] 本番環境での評価項目について導入の必要性を検討し、適切に導入している
    • Direct Feedback: ユーザーからの明示的なフィードバック(👍/👎等)
    • Functional Correctness: 生成結果が機能的に正しいか
    • User Acceptance: ユーザーが結果を採用したか(コピー、編集、実行等)
    • Achieved Impact: ビジネスKPIへの影響
    • Incidental Metrics: レイテンシ、エラーレート、コスト等

6-4. 継続的改善

  • [ ] 評価データセットを継続的に更新するための仕組みが整っている
    • 本番トラフィックから評価データセットへのサンプリング
    • 失敗ケースの追加プロセス
  • [ ] 評価データセットのバージョン管理がされている
  • [ ] プロンプトバージョン・モデルバージョン・評価データセットバージョン・パラメータを1単位として評価結果を管理する仕組みが整っている
    • 実験管理ツールで各バージョンの組み合わせと評価結果を記録

6-5. 自動テスト

  • [ ] LLM API呼び出しを含む主要なE2Eテスト(正常系)が自動化されている
  • [ ] プロンプトやモデル変更時に、品質評価セットを用いた回帰テストが自動化または半自動化されている
  • [ ] 負荷テストが自動化または半自動化されており、リリース前に負荷テストを行う基準がチーム内で合意されている

7. セキュリティとコンプライアンス

不正アクセスやデータ漏洩、意図しないモデルの振る舞いを防ぎます。

7-1. データ保護

  • [ ] LLMへの入力データのうち、PII等のセンシティブ情報が分類され、マスキング対象が特定されている
    • 分類基準(例: PII、機密情報、公開情報)が定義されている
    • マスキング対象のデータ種別(例: 氏名、メールアドレス、電話番号、住所等)がリスト化されている
  • [ ] 転送中および保存データが暗号化されている
    • 転送中: TLS/HTTPS
    • 保存時: ディスク暗号化、データベース暗号化

7-2. プロンプトインジェクション対策

  • [ ] プロンプトインジェクション対策として、多層防御の仕組みが実装されている
    • 入力検証・サニタイゼーション
    • プロンプトテンプレートの使用(ユーザー入力を直接連結しない)
    • 出力の検証・パース
  • [ ] ユーザー入力とシステム指示が明確に分離されている
    • システムプロンプトとユーザー入力の役割分離(system role / user role)

7-3. アクセス制御

  • [ ] LLM APIの認証に、長期的なAPIキーやサービスアカウントキーを使用せず、一時クレデンシャルによる認証方式を利用している
  • [ ] APIへのアクセスが適切に認証・認可されている
    • ユーザー認証(必要に応じて)
    • リクエスト元の検証

7-4. モデルのリスク管理

  • [ ] ユーザー入力がLLMの学習データとして利用されないよう設定されているか、リスクが評価・受容されている
    • LLMプロバイダーのデータ利用ポリシーを確認
    • オプトアウト設定(必要に応じて)
  • [ ] 社内のモデル利用ポリシーに沿って利用モデルを選定している
  • [ ] Open‑weightモデルを利用する場合、Pickle形式ではなくsafetensors形式を利用している

8. ドキュメントと組織運営

チームメンバーがシステムを理解し、スムーズに運用できるようにします。

  • [ ] システム概要・システム構成図・依存関係図が最新の状態に保たれている
  • [ ] 主要なアラートへの対応手順(Runbook)や障害対応プロセスがドキュメント化されている
  • [ ] 障害発生時のインシデント対応プロセスが定義されており、インシデント発生後のポストモーテム(振り返り)を実施し、再発防止策を講じるプロセスが確立している

タイミーでの実装ガイド

本ガイドは、上記チェックリストを踏まえ、DS Gの技術スタック(Google Cloud、Datadog等)を踏まえた具体の実装例に落とし込んだものです。

1. 安定性・信頼性

構成管理

  • コード管理: Git(GitHub)でコード管理
  • プロンプト管理: Gitでプロンプトファイルを管理、またはプロンプトバージョニング機能を持つツールを使用

CI/CD

  • CI: GitHub ActionsでLint・テスト・SASTを実行
  • CD: GitHub ActionsからGoogle Cloud(Cloud Run)へ自動デプロイ

リリースプロセス

  • 段階的ロールアウト: Cloud Runのトラフィック分割機能、またはリリース管理ツールを使用

2. スケーラビリティとパフォーマンス

キャパシティプランニング

  • オートスケーリング: Cloud Runの「最大インスタンス数」「最小インスタンス数」「同時実行数(concurrency)」を設定

3. 耐障害性と大惨事対応

回復性テスト

  • 負荷テスト: Locustを負荷テストツールとして使用

4. 安全性

ガードレール

  • 違反記録: 構造化ログまたはDatadogイベントとして記録

5. 監視

アプリケーションロギング・トレーシング

  • APM: Datadog APM(Cloud Runのサイドカーに datadog/serverless-init を設定)

可視化とアラート

  • ダッシュボード: Datadog Dashboard、Looker
  • アラート: Datadog Monitor、Slack連携

LLM Observability

  • LLM監視: Datadog LLM Observability

6. 品質保証(QA)と評価プロセス

オフライン評価セット

  • データセット管理: Datadog LLM ObservabilityのDatasets機能の利用、またはBigQuery・GCSをベースとしたデータセットのバージョン管理

継続的改善

  • 実験管理: MLflow、Datadog LLM Observability

7. セキュリティとコンプライアンス

アクセス制御

  • 認証: Workload Identity Federation(GCP)等

モデルのリスク管理

  • タイミー社内の基準を満たすモデルを利用している

振り返りと今後の取り組み

これまでDS Gでは、データサイエンティスト中心のCSチーム(Complicated Subsystem Team)とMLOps(Platform Team)がCollaborationモード(Embedded SREに近い形)の関わり方で、LLMアプリケーションの構築・運用に取り組んできました。これは初期の知見蓄積と開発のアジリティ確保の点で、不可欠で有効なものでした。

しかし、今後サービスが増加するにつれ、この密な連携体制が組織全体のスケールのボトルネックになる懸念がありました。そうした課題を乗り越えるため、MLOpsチームは、CSチームが高速に高品質なアプリケーションを構築できるようなゴールデンパスの整備を進めています。

今回のチェックリスト作成は、その一つの取り組みとして知見を整理し、また現状の課題を再認識するものになったと考えています。

今後DS Gでは、RAGやAgentic Workflowのような、より複雑性の高いアプリケーションの構築や、LLM Gatewayといった基盤導入が控えています。

そうした複雑な課題に対し、CSチームとMLOpsチームがそれぞれの強みを発揮し、協調しながらスケールしていける体制が不可欠だと考えています。 本チェックリストの活用・改善を含め、常により良い協業の形を模索し、再現性高く信頼性のあるML/LLMアプリケーションによる価値創出にチャレンジしていきたいと思っています。

【現地レポート】Coalesce 2025:Opening Keynote “Rewrite”

こんにちは!株式会社タイミーでアナリティクスエンジニアをしているひろろと、データエンジニアをしているつざきです。

本記事は、二人の共同執筆という形式でお届けします!

現在、私たちはアメリカ・ラスベガスで開催されているdbtの祭典「Coalesce 2025」に現地参加しています! Coalesce 2025は、年に一度世界中のdbtユーザーが集まり、機能アップデートや事例発表、ハンズオンなどが行われるdbtの技術カンファレンスです。

当社ではデータ基盤にdbtを採用しているため、最新技術のキャッチアップを積極的に行っています。Coalesceへの参加もその一環として決まりました。 ※アーキテクチャのついて詳しくはこちら

また、今回はカンファレンス参加支援制度「KaigiPass」を利用して参加しております!

速報を現地の熱気とともにお届けします。ぜひご覧ください。

Day 1

初日には有料のトレーニング中心で、夕方からカンファレンスのキックオフとウェルカムパーティーが開催されます。

キックオフでは近くにいる人との自己紹介タイムがあり、最初は焦りましたが、みんな技術者同士。英語が苦手でも温かく受け入れてもらえる優しい雰囲気でした。 Coalesceのイベント内容や会場案内などを中心に紹介され、これから始まるセッションへの期待が高まる良い時間でした。 (決してモーニングやランチが出ることに喜んでいるだけではありません笑)

キックオフの後は、ウェルカムパーティーの開催です!立食パーティーの形式で実施され、パートナーブースで話を聞いたり、他の来場者との会話を楽しんだりできます。

同じ日本人の参加者とも交流することができ、データに関する話題で盛り上がりました。日本開催のカンファレンスとは違い、日本人が少ない分、数少ない日本人同士で仲間意識が芽生え、より深い話ができたように感じます。

また、パートナーブースの方も熱気がすごく盛り上がっていました。日本で開催されるカンファレンスよりも、皆さんのテンションが高いです。実際にブースへ行ってみてデモをみせてもらうだけでもためになります。どのブースにもAIという文字が記載されているのが印象的でした!

Day2

初日はKeynoteや数多くのセッションに参加しました。セッションの数がとても多いため、吟味するのがとても大変です。また、ランチの時は同じテーブルに座った方が気兼ねなく話しかけてくるので、そこでの会話も貴重な時間でした!

Opening Keynote

Keynoteはホテル内のシアター会場で行われました。前方席に座ったのですが、両サイドのスクリーンにリアルタイム字幕が表示されていたため、後方の方が見やすかったと後で気づきました。

Opening Keynoteでは「Rewrite」というキーワードが繰り返し登場し、印象的でした。dbt LabsのCEO、Tristan Handy氏をはじめとした登壇者たちが、AI時代におけるデータワークの再定義について語りました。

まず大きな話題として取り上げられたのが、Fivetranとの合併についてです!前日の10/13に発表されたばかりのため、この場で話を聞けることを楽しみにしていたのが、歓声から伝わってきます。

その流れで呼ばれたのが、FivetranのCo-Founder & CEOであるGeorge Fraser氏。Fivetranのコネクタバグ修正の話から始まり、dbtに対して初めは懐疑的だったが変わっていったこと、dbtをAIが今後重要となっていく中で将来性や相互運用性が合併の背景としてあること、dbtへの破壊的な変更はないことなどをトーク形式で語っていき、dbtユーザーを安心させ一緒にdbtを盛り上げていきたいという気持ちがとても伝わる内容でした。

次に、Metric Flowついて大きな発表がありました。

MetricFlowは、dbt Labsが提供するメトリクス管理の製品です。今回、Apache 2ライセンスでのオープンソース化が発表され、会場から大きな拍手が起こりました。 「ベンダーロックインが懸念で導入に踏み切れなかった」という声も多く、まさにその課題に応える発表でした。

参考URL:https://www.getdbt.com/blog/dbt-labs-affirms-commitment-to-open-semantic-interchange-by-open-sourcing-metricflow

その次に語られたのが、dbt Fusion エンジンになります。

dbt Fusionエンジンは「Rewrite Developer Experience」をテーマに、開発体験の抜本的な刷新を目指した機能群として紹介されました。 実際のデモでは、従来より最大30倍のコンパイル高速化や、CTEプレビュー・カラムレベルのエラー検知などが披露され、歓声が上がる場面もありました。

機能についての詳細は公式ドキュメントをご覧ください。

SDF Labsの共同創業者で、dbt Fusionエンジンのプロダクトリーダーを務めているElias DeFaria氏によるライブデモでは、dbt Fusionエンジンがもたらす多くの開発支援機能が実際に披露され、会場からは何度も歓声が上がりました!

「Column rename propagation」など機能が発表される度にドヤ顔をしている担当者を近くで見られることは現地参加の醍醐味ですね!

特に、新たに発表された「Compare changes」は、変更を本番環境に適用する前にデータへの影響を確認することができます。本番にマージしてからデータがおかしくなってしまっていることに気がつく、といった肝が冷えるやらかしを削減できる素晴らしい機能だと思いました!

次に発表されたのは、State-aware orchestration です。

State-aware orchestrationは、Fusionの機能を活かしたインテリジェントな実行制御機能です。依存関係の入力データが変更されたモデルのみを再構築することで、無駄な再実行を防ぎます。 発表によると、この機能を有効化するだけで約10%のコンピュートコスト削減が見込まれるとのことです。(すごい!)

また、State-aware orchestrationのさらなる最適化として、Tuned configurationが紹介されました。

Tuned configurationでは、ユーザーは「Freshness要件の宣言」をすることができ、年間コンピュートコストを少なくとも29%削減できる見込みが示されました。

dbt内部ではこれらの最適化を導入することで最終的に64%もコストを削減できたとのことです。すごすぎる!

そして、最後に発表されたのがdbt Agentsです。

dbt Agentsでは4つの新しいサービスが発表されました。

サービス名  機能・コメント 状態
Developer Agent (開発者エージェント) 変更内容を記述するだけで、エージェントがそのタスクを実行し、SQLファイルの作成、テスト、ドキュメント化を自動で実行してくれるとのこと!アツイ! 近日公開
Observability Agent (可観測性エージェント) パイプラインの障害箇所を特定し、修正を支援してくれるエージェントです。これによってトラブルシューティングに費やす時間を削減しアラートの削減につながることが期待されます 近日公開
Discovery Agent (発見エージェント) カタログやドキュメントから承認済みのデータセットと定義を識別し、なぜそのデータが信頼できるのかを示します。ただの検索ではなく信頼性の高いデータを見つけるまでの時間が削減できるとのことです ベータ版
Analyst Agent (アナリストエージェント) 会話型分析(conversational analytics)の構築を支援し、複雑な質問に対してガバナンスされた回答を提供してくれるとのことです ベータ版

全てのAgentが、データ分析開発における「あったらいいな」を実現できる機能のように思えました。特に個人的には、Developer Agentは、テキストで指示するだけで自律的に実装を行ってくれる、おそらくDevinのような開発体験ができるのかなと感じていて期待が膨らみます。

まとめ

本記事では、Coalesce 2025の現地の様子とOpening Keynoteの内容を中心に紹介しました! dbt LabsとFivetranの合併、Metric FlowのOSS化、Fusionエンジンによる高速化、State-aware orchestrationによるコスト最適化など、「Rewrite(書き換え)」というテーマにふさわしい革新が詰まったセッションでした。 今後、残りのセッションで各機能の詳細や導入事例を調査し、続報をお届けする予定です。ぜひご期待ください!

スプリントゴールに集中して、価値が駆動出来るチームになるために輪読会を実施しました

はじめに

こんにちは!今回は(@arus4869@yoshi_engineer_ )の2人で執筆しました! この記事では、私達のチームが『スプリントゴールで価値を駆動しよう』という書籍の輪読会をきっかけに、形骸化しがちだったスプリントゴールを「チームの羅針盤」として機能させ、スプリントの達成率を体感値で50%から80%に向上させた具体的な実践記録をご紹介します。

この記事は、特に以下のような課題を感じている方に読んでいただきたいです。

  • スプリントゴールが「タスクリスト」になりがちで、なぜやるのか(Why)やどんな価値が生まれるのか(Outcome)が曖昧になっている。
  • スクラムを実践中で、スプリントゴールの質に悩んでいる。
  • ステークホルダーやチームメンバーと機能の話はできても、「価値」についての会話がしづらい。

なぜこの本を選んだのか

私達のチームも、まさに上記のような課題に直面していました。

スクラム開発を長く続けているものの、いつしか「フィーチャーファクトリー」のようになり、スプリントゴールが単なるタスクリストになっていました。チームとしてやりたいことが多すぎて常にバックログを積みすぎる傾向があり、「レビューで何を学んだか」をアウトカムで語ることが難しく、アウトプットの話に終始しがちでした。

この「なんとなくこなすだけ」の状態を脱却したい。そんな思いで、スプリントゴールを考え直すヒントを与えてくれそうな本書を、輪読会のテーマとして選びました。

そもそもスプリントゴールとは何か?

スプリントゴールはなぜ設定されるのか知っていますか?私は説明することができませんでした。

スクラムガイドでは以下のように定義されています。

スプリントゴールはスプリントの唯⼀の⽬的である。スプリントゴールは開発者が確約するものだが、スプリントゴールを達成するために必要となる作業に対しては柔軟性をもたらす。スプリントゴールはまた、⼀貫性と集中を⽣み出し、スクラムチームに⼀致団結した作業を促すものでもある。 スプリントゴールは、スプリントプランニングで作成され、スプリントバックログに追加される。開発者がスプリントで作業するときには、スプリントゴールを念頭に置く。作業が予想と異なることが判明した場合は、スプリントゴールに影響を与えることがないように、プロダクトオーナーと交渉してスプリントバックログのスコープを調整する。

スプリントゴールはスプリントの唯一の目的

スプリントにおいて、この目標を達成することこそが大本命なわけです。

では、その重要性を深ぼっていきましょう。

スプリントゴールがなぜ必要なのか?

スプリントゴールの重要性、まず挙げられるのは「チームの思考をタスクベースの「アウトプット」から、ユーザーに提供する「アウトカム」へと転換させる」ことです。

チームは「ユーザーへの価値の提供」を本来の目的として行っています。実際のチームを稼働していく際に、いつの間にかタスクリストのみを指針として作業を進んでしまう可能性があります。

例えば、「ユーザー登録画面の実装」や「データベース登録処理」といったタスクの羅列だけでは、開発者はなぜその作業を行っているのか、その作業が最終的にどのようなユーザー価値に貢献するのかがチームメンバーが共通して理解しにくい場合があります。

スプリントゴールがあることで、ユーザーに届けたい価値,アウトカムがタスクと連結して、一つの具体的なインクリメントを生み出すという明確な意図が共有されます。

このようにチームは「タスクの進捗」だけでなく、ゴールへの貢献度を常に意識できるようになり、より良い意思決定と協調性を生み出す。

スプリントゴールの効能

スプリントゴールがチームに対してもたらす効能は他にもあります。それは「集中」「一貫性」です。

チームに明確なゴールがなければ、チームはプロダクトバックログアイテム(PBI)がスプリントバックログに含まれる場合、それぞれのPBIが独立した作業として捉えられ、チームがばらばらに作業するリスクがあります 。このような状況では、チームとしての協調性が生まれず、特定のPBIを担当する個人が孤立したり、作業の詰まりが発生したりする可能性があります 。

スプリントゴールは、これらのPBIを「なぜ我々はこれらを同時に進めるのか」という共通の目的に集約します。共通の目的を持つことで、チーム全員が同じ目標に向かって努力し、一体感を高めることができます。

これにより、チームメンバーは「ゴール達成のために誰かを助ける」という動機付けが生まれ、協力して問題を解決する姿勢が自然に育まれます。個々のタスクの完了ではなく、チーム全体のゴール達成に焦点を当てるという、スクラムの本質を体現します。

良いスプリントゴールを建てるために

ここではタスクベースのゴール設定状態ベースのゴール設定についてお話しします。タスクベースのゴールでは、チームメンバーが「自分のタスクが終わらなかった」という個人の反省に終始し、ネガティブな内省に陥りやすい可能性があります。

スプリントゴールを「モヤモヤが解消された状態」や「特定の価値が提供された状態」といった「状態」ベースで設定すると、チームはプレッシャーから解放され、より前向きな振り返りがしやすくなります。

また、ゴールが未達成であっても、チームは「なぜその状態に至らなかったのか」という根本的な原因を客観的に分析することができ、これを次のスプリントでの改善点として捉えることができます 。

このようなプロセスは、チームメンバー間の信頼関係を深め、失敗を学習の機会と捉える健全な文化を醸成します。スプリントゴールの達成に向けて互いに助け合う習慣は、チーム全体の協力体制を強化し、個々のモチベーションを維持する上で重要な役割を果たします 。

スプリントゴールを駆動して成功の鍵として活用していくために

  • スプリントゴールが単なるタスク管理ツールではなく、チームの集中力、柔軟性、そして価値創出を最大化するための不可欠な要素です
  • スプリントゴールを「タスクのリスト」から「成果を示す羅針盤」へと進化させることで、チームは「何をするか」から「何を成し遂げるか」へと意識を変えることができます。

何を実践したのか(輪読会での取り組み)

輪読会での学びを元に、私達は以下の3つの具体的なアクションをチームに導入しました。

1. スプリントゴールの「決め方」を合意形成のプロセスに変えた

これまで曖昧だったスプリントゴールの決め方を、チームで合意を形成するための明確なプロセスに変更しました。具体的には、スプリントプランニングで以下のステップを踏んでいます。

  1. 全員でスプリントゴール案を1つ考える: まず、POだけでなくチーム全員でスプリントゴール案を出します。
  2. 自信度の可視化と投票: そのスプリントゴール案に対して、達成できる自信度を各自が表明し、参考情報として投票を行います(多数決でスプリントゴールを決めるわけではありません)。
  3. 対話と議論: なぜその自信度なのか、なぜその案が良いと思うのかを全員で対話し、納得解を探ります。
  4. 「FOCUS」で最終チェック: 最後に、そのスプリントゴール案が良いゴールの特性(※)を満たしているか、チームでチェックし、最終決定します。

※FOCUSとは? 良いスプリントゴールの特性を示した頭字語。Fun(楽しい), Outcome-based(アウトカムベース), Collaborative(協調的), Ultimate(究極的), Singular(単一)の5つの観点。

このプロセスにより、スプリントゴールが「誰かが決めた目標」から「自分たちが合意した目標」に変わりました。

2. 「やること」を勇気をもって絞り込んだ

過去の私達は、スプリントゴールに集中できずに品質を低下させたり、ゴール自体を達成できない経験がありました。本から「同時に多くの作業に取り組むことは、協働を妨げ、価値提供を減少させる」という原則を学び、輪読会中にチームの合意として以下のルールを決めました。

「スプリントプランニングでスプリントバックログに入れるのは、スプリントゴール達成に直接貢献するPBIだけにする」

これにより、チームのエネルギーが分散することなく、全員がゴール達成に集中できるようになりました。

3. レビューで「データ」を語ることを始めた

価値(アウトカム)を意識するため、スプリントレビューで関連するプロダクトのダッシュボードを参加者で見ることから始めました。まだ道半ばですが、これにより会話が「何を作ったか(Output)」から「それによって何が変わりそうか(Outcome)」へと少しずつシフトするきっかけになっています。

やった結果どうだったか(輪読会の成果)

これらの取り組みの結果、チームには明確な変化が生まれました。

  • スプリントゴール達成率が向上: あくまで体感値ですが、スプリントゴールの達成率は約50%から80%へと向上しました。
  • プランニングの質が向上: 「このPBIはスプリントゴール達成にどう繋がるんだっけ?」という問いかけが自然に生まれ、バックログ選択の迷いが減少しました。
  • デイリースクラムの会話が変わった: 単なる進捗報告ではなく、「スプリントゴールを達成するために、今日は〇〇をしようと思う」といった、ゴールを意識した会話が中心になりました。

参加者の声

輪読会の参加者の声を抜粋します。

総合的に輪読会に参加して良かったという感想になりました。

  • 「不確実性への対処」における説明やそれに対するソリューションが大変学びになった。
  • 一人で読むとインプットだけで終わりがちですが、チームですぐに実践できるのが輪読会の良いところだと感じました。
  • FOCUSは一つのHOWに過ぎないと思いつつ、輪読会から具体的なアクションが生まれたのはとても良いな〜と思いました。
  • 価値提供を重視し、FOCUSの考え方でゴールを打ち立てることが本を通じて印象に残りました。

まとめ

今回の輪読会と実践を通して、私達は重要な学びと気づきを得ることができました。

経験からの学び: 良いスプリントゴールとは、優れた文章以上に、チームで『何に集中し、何を顧客に届けるのか』を合意するプロセスそのものでした。

気づき: チームが共通のゴールに集中することで初めて、日々の行動が価値ある「得点」に繋がるのだと気づきました。

この記事で紹介した私達の「スプリントゴールの決め方プロセス」が、その一助となれば幸いです。

最後までお読みいただき、ありがとうございました。

【iOSDC Japan 2025レポート】タイミーエンジニアが注目した最新技術とリアルな開発事例

こんにちは、iOSエンジニアの大塚、山崎、早川(@hykwtmyk)、前田(@naoya_maeda) です。

2025年9月19-21日に有明セントラルタワーホール&カンファレンスで開催されたiOSDC Japan 2025に、タイミーもゴールドスポンサーとして協賛させていただきました。 イベントは以下のように、3日間連続で行われました。

9月19日(木):day0(前夜祭)

9月20日(金):day1(本編1日目)

9月21日(土):day2(本編2日目)

私たちもイベントに参加したので、メンバーそれぞれが気になったセッションや感想をご紹介します。

大塚 編

先日、iOSDC Japan 2025に参加しました。今年は会場が例年とは異なり、カンファレンス全体の雰囲気にいつもと違った新鮮な印象を受けました。私は毎年iOSDCに参加していますが、日々の業務や自己学習だけでは触れる機会の少ない、高度でニッチな領域の知識を集中的に得られる点が、本カンファレンスの最大の魅力だと感じています。本レポートでは、その中でも特に印象に残った「金融サービスの成長を支える "本人確認フロー" の改善と取り巻く環境の変化」のセッションについてご報告いたします。

概要

セッションは、1. 本人確認フローの改善と2. 法令改正など取り巻く環境の変化についての発表でした。

1. 本人確認フローの改善

前半は、JPKI方式を用いた本人確認の実装戦略についての解説でした。リードタイムを短縮するため、マイナンバーカードの読み取りおよび電子証明書の検証といった機能は、外部ベンダーが提供する SDK を用いて実装しているそうです。一方で、ユーザーが直接触れるUI部分はあえて自社で開発するという戦略を採っています。UIを自社で開発することで、離脱率を改善するための様々な実験的な施策をスピーディーに導入し、その最適化のメリットを享受されているそうです。

2. 法令改正など取り巻く環境の変化

後半は、金融サービスを取り巻く犯収法などの法令改正がいかにアプリ開発に影響するかについてです。特にJPKIの署名用電子証明書を用いる方式やカード代替電磁的記録を用いる方式など、外部環境の変化にエンジニアがどう対応すべきかに焦点を当て解説されていました。

感想

私が所属するチームで担当している本人確認フローに関する発表だったため、特に強い関心を持って拝見しました。他社ではどのようにJPKI方式を実装し、離脱率の改善という難しい課題に対し、どのような観点で技術やプロダクト設計の選択を行っているのかを具体的に知ることができ、大変勉強になりました。

山崎 編

iOSDCは今回初めて参加させていただきました!

初参加だからこそ感じた現地の熱気やセッションの感想などをレポートします。ちなみに、私はday0とday2の2日間参加しました。

day0:カンファレンスの熱気に触れる

day0ではまず、プレオープニングセッションに参加し、iOSDCの歴史やコミュニティの成り立ちについて知ることができました。多くの開発者の情熱によってこの素晴らしい場が作られていることを知り、参加できることへの感謝の気持ちで胸がいっぱいになりました。

その後は、弊社の岐部さん(@beryu)の発表を応援しに行ったり、興味のあるセッションをいくつか拝見しました。どれもレベルが高く、知的好奇心を強く刺激される内容ばかりでした。

day2:ブースでの交流

day2では、弊社のブースに立ち、たくさんの参加者の方々とコミュニケーションを取らせていただきました。

私たちのブースでは、「最近うまくいったこと」をテーマに付箋を書いてもらう、という企画を実施していました。これをきっかけに会話が弾み、「最近、SwiftUI化がうまくいったんです」「AIをこう活用して業務改善しました」といった具体的なお話をたくさん伺うことができました。特にAI活用のトピックは多くの方の関心事のようで、他社さんのユニークな取り組みを聞けたのは大きな収穫でした。

心に残ったセッション

業務で直接関わる機会の少ない領域でのセッションを機会が多かったのですが、どれも新鮮で非常に面白かったです。

  • 手話ジェスチャーの検知と翻訳~ハンドトラッキングの可能性と限界~ fortee.jp

  • Apple Vision Proでの立体動画アプリの実装と40の工夫 fortee.jp

  • プログラマのための作曲入門 fortee.jp

  • 「iPhoneのマイナンバーカード」のすべて fortee.jp

特に、Apple Vision Pro関連のセッションは、従来のアプリ開発とは異なり、3D空間上でUIやUXをいかに自然に見せるかという点に多くの工夫が凝らされており、大変興味深かったです。オブジェクトを空間に違和感なく配置することの難しさを改めて感じました。

マイナンバーカードの話は、実際にどのようなAPIが使われているのかという技術的な解説が非常にためになりました。アプリ内、対面、ブラウザの3種類のVerifier APIの具体的な使い方やユースケース、さらにはmdocのデータ構造や日本のために作られたAPIの紹介など、普段は知ることのできない実装の詳細に触れることができ、とても貴重な体験でした。

SwiftコードバトルとLT大会の熱気

Swiftコードバトルは、制限時間内に要件を満たすプログラムを、Swiftでいかに短く書くかという競技で、緊張感のある中、参加者の方々のコーディングスピードと発想力に圧倒されました。

LT大会は、参加者がサイリウムを振って会場全体が一体となる、ライブのような賑やかな雰囲気でした!特に印象的だったのは、課金周りのLTが続いた時間帯です。各社それぞれの知見や工夫が凝縮されており、とても勉強になりました。

初めてのiOSDCは、技術的な学びはもちろん、何よりもコミュニティの温かさと熱量を肌で感じられる最高の体験でした。ブースでの交流、刺激的なセッション、そしてユニークな企画までとても熱狂感のある素晴らしいイベントでした!

早川 編

タイミーでiOSエンジニアをしている早川です。 一昨年ぶりにiOSDC Japan 2025にオフライン参加してきました!今年から会場が変わり、またいつもと違う雰囲気でしたね(個人的には、自宅から近くなったので嬉しいです)。

さて、いくつかのセッションを聴講した中で、特に学びが多かったのが、デスクスさんが発表された「5000万ダウンロードを超える漫画サービスを支えるログ基盤の設計開発の全て」です。

speakerdeck.com

大規模サービスにおけるログ基盤という、普段なかなか知ることのできない領域について、詳細なコードベースでの解説や実践的な知見が共有されており、多くの学びがありました。本記事では、発表内容の要点と特に印象に残った点についてまとめていきます。

発表の要点

1. 新ログ基盤「Tracker」の設計思想と特徴

パフォーマンスと柔軟性の向上を目的とし、モダンな技術スタックを全面的に採用。Swift 6のSendableに準拠した設計をベースに、並行処理による高いパフォーマンス、gzip/deflateによるデータ圧縮、そしてモバイル環境の不安定なネットワークを考慮したExponential Backoffによる堅牢なリトライ戦略が主な特徴として挙げられていました。

2. Clean Architectureによる責務の分離

アーキテクチャにはClean Architectureを採用。Entity、Use Case、Data Layer、Public Interfaceを明確に分離することで、各コンポーネントが独立して機能し、テスト容易性や変更容易性が格段に向上したとのことでした。これにより、全体で80%以上という高いテストカバレッジも実現していました。

3. Firebase Remote Configを活用した安全な移行戦略

Firebase Remote Configをフラグとして利用し、旧基盤と新基盤を並行稼働させ、いつでも切り戻しが可能な状態で段階的に移行を進めるという、非常に現実的でリスク管理に優れたアプローチが紹介されました。

特に印象に残った点・感想

この発表では、ログ基盤というテーマに留まらず、大規模なモバイルアプリ開発全般に役立つ知見が随所に見られました。

ログの送信自体はユーザーの目に見えない部分ですが、メインスレッドをブロックしない、メモリを圧迫しないといったユーザーファーストな視点と、テスト容易性を高めるアーキテクチャ設計や高いテストカバレッジといった開発者としてのこだわりが見事に両立されており、まさにユーザーと開発者の双方にとって「Win-Win」な内容だと感じました。

また、Firebase Remote Configの活用法も非常に印象的でした。特に「将来的に全体公開する前提のConfigは、デフォルト値をtrueにしておくことで、移行完了後にConfigを削除できる」という知見は、私自身も過去に逆の設計で失敗した経験があるからこそ、大変共感しました。

このように、自身の業務でもぜひ参考にさせていただきたい学びの多い、素晴らしい発表でした。

前田 編

僕は今年が二回目のiOSDCへの参加でした。今回も幅広いジャンルで興味深いトークがたくさんありました。その中で、僕が最も面白いと感じたセッションは、かっくんさんの「独自UIで実現する外部ストレージデバイスの読み書き」でした。

fortee.jp

偶然なのですが、ちょうどこのトークの前日に、僕が個人的に調査を始めたトピックでした。

僕にとってはすごくホットなトピックだったこと、デモを交えた聴講者を惹きつけるトークが魅力的に感じたのでこちらのトークを選びました。

このトークは、iPhoneで撮影した写真や・ビデオデータを外部ストレージに直接保存する方法を紹介する内容です。まだ情報自体が少ないこともあり、Appleのエヴァンジェリストの方と一緒に調査を進めて、実装を実現したエピソードを交えたトークになります。

iPhoneのカメラで撮影した写真や・ビデオデータを保存する場所や方法は、大きく2パターンが用意されています。

一つ目の方法は、iPhoneのストレージに保存する方法ですね。こちらの方法は最もよく知られており、サンプルコードも豊富で難易度はそこまで高くありません。PhotoKitフレームワークを使用することで、10行程度のコードで実現することができます。

zenn.dev

二つ目の方法は、iPhoneに接続している外部ストレージに保存する方法です。こちらの方法は、さらに2パターンに分かれています。 一つ目の方法は、UIDocumentPickerViewController または、.fileExporter モディファイアを使用する方法です。これらのAPIを使用することで、データを外部ストレージに保存することができます。しかし、これらの方法では、ユーザーにデータの保存先を選んでもらう必要があります。ユーザーは、データの保存先を選択することができるメリットがある一方、ユーザーの操作数を増やしてしまうことになります。 そこで今回のトークで登場したAPIが、AVExternalStorageDevice です。iOS 17から使用可能な比較的新しいAPIです。このAPIと関連APIを使用することで、iPhoneに接続している外部ストレージに、データを直接保存できます。実装コストも高くなく、数十行程度のコードで本機能を実現できることを知れて、僕にとっては学びが多いトークでした。

本トークでは、実際に会場で撮影した写真を、iPhoneに接続されている外部ストレージに直接保存し、保存したデータ一覧を表示するといったデモもあり、楽しくトークを聴くことができました。

最近では、高ストレージ端末を除いては、ProRes Logデータを撮影する時に外部ストレージとの接続が必須になってきています。今後、外部ストレージ接続が必須になる機能が増えるかもしれない状況になる可能性もあるので、さらに深掘りを進めてみたいと思います。

最後に

この3日間を通して技術的な知見を深めたり、久しい友人に会って話をすることができ、すごく有意義な時間を過ごせました。この場を用意してくださったiOSDCスタッフの方々、参加者のみなさん本当にありがとうございました!

上記で紹介したセッション以外にも非常に興味深いセッションが多くありました。 記事にある内容や、その他の内容についても、もしタイミーのエンジニアと話したいという方がいらっしゃればぜひお気軽にお話ししましょう!

Kaigi on Rails 2025 に参加しました

タイミーの江田、徳富、神山、亀井、桑原、志賀です。 KaigiPass という制度を利用して Kaigi on Rails 2025 に参加してきました。タイミーは昨年に引き続きスポンサーをさせていただき、今年はなんと幸いなことにブースも出させていただきました。今回はそんな Kaigi on Rails 2025 の参加レポートを KaigiPass を利用したメンバーで記述していこうと思います。

2分台で1500 examples 完走!爆速 CI を支える環境構築術

Hiroshi Tokudomi

https://kaigionrails.org/2025/talks/falcon8823/#day1

「2分台で1500 examples 完走!爆速 CI を支える環境構築術」というタイトル通り、CI をどのように高速化していくかについての発表でした。

弊社でも現在 self-host runner を使って GitHub Actions 上で CI を回しており、2 万 2 千件のテストを平均 9〜10 分程度で実行しています。CI は短ければ短いほどいいものなので、このセッションタイトルを見たときに「これは絶対に見に行こう」と思ったのですが、まさに期待通り参考になる内容でした。

テストを並列に分割して実行する方法として Knapsack Pro が紹介されており、自分たちが使っている split-test と比較しながら聞くことができました。Knapsack Pro は実行時間の履歴をもとに分割を最適化できるとのことで、今後検討してみたいと思います。

また、EBS の I/O がボトルネックになることで CI が遅くなる話も印象的でした。弊社でも CI 実行が重なると I/O 使用率がギリギリまで上がることがあり、tmpfs を使うことで改善できる可能性があるのでは、とワクワクしながら聞いていました。

ちょうど最近 CI 基盤を self-host runner に移行したばかり(参考)ということもあり、「次はどこをチューニングできるか」と考えていたタイミングでのセッションだったので、個人的にはかなり刺さりました。CI をどう速くするかは日々の開発体験に直結するテーマなので、今回の学びを持ち帰って改善につなげていきたいです。

https://speakerdeck.com/falcon8823/2fen-tai-de1500exampleswan-zou-bao-su-ciwozhi-eruhuan-jing-gou-zhu-shu-kaigi-on-rails-2025

dynamic!

Keisuke Kuwahara

https://kaigionrails.org/2025/talks/moro/#day1

https://speakerdeck.com/moro/dynamic

1日目のキーノート「dynamic!」は、静的なアプローチとは対照的に、最初から完璧なゴールを目指すのではなく、継続的に変化していくプロセスを重視するテーマでした。

セッションでは、開発を細かく進めるための第一歩として、「ハッピーパス」の実装が重要だと強調されていました。ハッピーパスとは、ユーザーが使える「最小限かつ最もシンプルな機能」のことであり、これをまず実装することで、早い段階でフィードバックを得て、改善サイクルを回すことが可能になります。

特に印象的だったのは、開発者だけでなく、チーム全体で変化を起こしていくという考え方です。私自身、複雑な機能を実装する際、最初からすべてを網羅しようと時間をかけた結果、いざデモをしてみると多くのフィードバックをもらった、という経験があります。その時はできるだけ指摘をもらわないように実装しよう、という気持ちになっていましたが、今回の話を聞いて、動くものをいち早くチームメンバーやステークホルダーに確認してもらい、早くフィードバックを得ることの重要性を再認識しました。

またこれまでは、優秀なエンジニアほど、一発で完璧なプロダクトを作るものだ、と漠然と思っていましたが、実際は逆でした。経験豊富なエンジニアほど、最小限の開発から始め、段階的な改善を積み重ねていくのだと気づきました。

アジャイル開発は今のチームでは当たり前になっていますが、「動的に変化し続けること」の重要性を改めて深く感じました。完璧主義にとらわれて最初の実装に時間をかけるのではなく、変化を恐れずに、その時々で最もシンプルな方法を実践していきたいと思います。

「技術負債にならない・間違えない」 権限管理の設計と実装

Akitoshi Shiga

https://kaigionrails.org/2025/talks/naro143/#day2

https://speakerdeck.com/naro143/ji-shu-fu-zhai-ninaranaijian-wei-enai-quan-xian-guan-li-noshe-ji-toshi-zhuang

Webサービスにおいて頻出の課題である権限管理に対して、自社のプロダクトで行った取り組みを発表されていました。

権限管理のありがちなアンチパターンとして、権限の判定が必要な場所で操作者の役割を判定するような実装についてあげられていました。

例: あるControllerのcreateアクション内でif admin?

役割を判定する場合は、判定する箇所が役割ごとに何ができるかを把握する必要があります。

役割ごとの権限は、サービス内容や事業環境の変化が激しい状況においてはすぐに複雑化します。

その上、この実装では権限を変更するたびに、すべての判定箇所に手を加えなければいけません。

その結果としてすぐに保守が困難になります。

そこで、役割=何者であるかではなく権限=何ができるか に依存すること、その上で、権限管理に必要な要素である「対象」「操作」「役割」「条件」に対する記述を分離・明文化した設計を発表されていました。

具体的には、module分けした「対象」ごとに「役割」のクラスを作り、「操作」に紐づいたメソッド内で「条件」を判定する実装を行っていました。

これによって、対象ごとに役割が操作を行うための条件が非常にシンプルになりました。

https://speakerdeck.com/naro143/ji-shu-fu-zhai-ninaranaijian-wei-enai-quan-xian-guan-li-noshe-ji-toshi-zhuang?slide=64

その結果、カスタマーサポートやプロダクトマネージャーがGitHubでコードを読んで理解できるようになり、社内からのエンジニアへの権限に関する問い合わせが0になったそうです。

所感として、操作する対象が増えるたびにすべての役割のクラスを作成する必要があるものの、条件というコアなロジックは一箇所に集中されるので保守しやすそうだと感じました。

また、権限という複雑なビジネスロジックを非エンジニアが理解できるほどシンプルにコードで表現されていることに感銘を受けました。

複雑なビジネスロジックにちゃんと向き合ってシンプルな表現を目指すことの効果と大切さを今一度実感しました。

Railsによる人工的「設計」入門

Yutaka Kamei

https://kaigionrails.org/2025/talks/nay/#day1

亀井です。万葉の大場さんのこちらのセッションが素敵だなと思ったので、このセクションを書かせていただいています。私なりにこの発表を解釈すると、設計がうまくなる方法について深掘りした内容だったのかなと思います。この AI 時代にコーディングを AI に任せることは増えてきた中で、人間が設計をできることの重要性がとても高まっています。そんな中で、どのようにしてもっとうまく設計ができるようになるのか?というのをご自身の偶然の経験から形式知にしてまとめてくださった内容でした。

完成したシステムを思い浮かべてそこから「逆算」して考えていくとよいのではないか?というのが重要そうでした。私の経験でも、ゴールを思い浮かべてそこに至るまでのマイルストーンを描きステップを重ねるというやり方がよいのではないか?ということを思っていたので非常に納得感があります。まさに全体から部分へ、という思考を行うことによってうまく設計ができる、という考え方ですね。たしかに、 Ruby on Rails が MVC をベースにしたフレームワークだからといって、モデル→コントローラー→ビューという順番に書く必要もないですし、むしろその順番で書くと全体が見えない状態で開発をすることになるので、次第につぎはぎだらけのコードが生成されてしまいます。その場しのぎのコードになってしまうと、やはりそれはそれで今後のメンテナンス性に影響してくるわけです。あるべき状態、あるいは本質的なゴールを描いてそこから「逆算」する、という考え方の言語化がとても素敵でした。

また、名付けの重要性について語っておられたのもよかったですね。 Ruby 界隈では「名前重要」というのはよく知られていると思いますが、設計の上でなぜ名付けが重要なのか?ということについての言語化もクリアでわかりやすかったです。たしか、コードのレベルではなく、抽象度の高いレベルで短い名前をつけながら考えを進めて「デザインパーツ」を取捨選択し「仮置き」することが重要というようなこともおっしゃっていたと思います。「仮置き」というワーディングがよいですね。たしかに、「決定」というと後戻りができない感じがしますが、「仮置き」というのは「変更の余地があること」を示唆する感じがして、日本人としてこういう日本語表現を利用できるのはとてもラッキーだなと思います。そういえば、「仮置き」で思い出しましたし、このセッションで参照されたキーノートの dynamic! にもあったように、オプショナリティーについて言及が最近増えましたね。「仮置き」という用語にもオプションというニュアンスを感じます。『Tidy First?』を読んで私なりにオプションについて理解をしているつもりでしたが、こうしていろいろな登壇を聞いて私なりの解釈もそこそこあってそうな予感がしてうれしさを感じています。みんな Kent Beck が好きですよね。私もです。

今改めてServiceクラスについて考える 〜あるRails開発者の10年〜

Yuki Eda (edy)

https://kaigionrails.org/2025/talks/joker1007/#day1

Ruby on Railsでアプリケーション開発に従事しているエンジニアであれば一度は通るであろうServiceクラス。2025年のこのタイミングでjokerさんがこのタイミングで発表を行う理由も気になり視聴しました。

冒頭で歴史的な経緯を含めて日本国内で布教した背景の考察や、『パーフェクトRuby on Rails』にてServiceクラスを題材に執筆された当時の意図、執筆後数年経ってからの[Qiitaでのエントリ](https://qiita.com/joker1007/items/25de535cd8bb2857a685)などに触れられつつ、Serviceクラスに対しては出来る限り使わない方が良いと結論づけられていました。理由は「開発統制の困難さを上回るメリットが得られない」とのこと。

この点、私も思い当たる節はあり、例えばFat Modelを解消する手段としてServiceクラスを選択していた過去があります。適切な命名付けをしたとしても、アプリケーションの成長や数年間の運用の過程で特定のドメインだけの処理で留まらずに肥大化したトランザクションスクリプトになる傾向があると思います。これはjokerさんも言及されていた「基準の作りにくさ」から来る部分や、適切なドメインモデリングを怠った結果の2つが大きな原因だと、発表を聞きながら改めて考えさせられました。

結局のところ、ビジネスにおける関心事を顧客やチームメンバーを交えながらシステム内でうまい具合に表現できるするか、その丁寧な抽象化と具体化の繰り返し作業が大事で、Serviceクラスもそうですし対抗馬として挙げられることの多いFormクラスも含めて、デザイン方法は表現技法の一つに過ぎないということですね。

発表の末尾のスライドの「正解はない、一緒に考え続けましょう」「ソフトウェア設計は継続的な営み」が非常に印象的で心に留めておきたいと思いました。

履歴 on Rails : Bitemporal Data Modelで実現する履歴管理

Daichi Kamiyama - dak2

https://kaigionrails.org/2025/talks/hypermkt/#day2

https://speakerdeck.com/hypermkt/history-on-rails-with-bitemporal-data-model

直近で履歴を残すかどうかの設計に頭を悩ませたことがあり、Bitemporal Data Model での履歴管理の良し悪しが気になったので、拝見させてもらいました。

履歴テーブルのパターンとして参考になるのは、一休さんの https://user-first.ikyu.co.jp/entry/history-table このスライドが非常に参考になると思っています。普通に“履歴”という概念を表現するのであれば、このスライドの内容に沿って場合分けしていけば多くの場合は網羅できるんじゃないかと思っています。

ただ、SmartHR さんが扱うドメインとして “従業員を起点とした変化” に向き合っていく場合、「あとから分かった出来事も正しい日付で反映したい」というニーズがあるようです。確かに言われてみればそうですよね。

レコードとして有効な期間(ex. 2025/09/26 までに役職が部長だった)と、操作時間の2つの時間軸で履歴を管理するコンセプトが Bitemporal Data Model です。有効な期間だけだと、そのレコードがいつ登録/無効になったかの事実が抜け落ちるので、2つの時間軸で管理しようという話のようです。

パッと直感的に思ったのは2つの時間軸を考慮しないといけないので、考えることが掛け算で増えてしまう懸念を持ちました。SQL も複雑になりそうですしね。後から有効な期間を追加したい場合に、有効期間が重複してはいけないと思うので、そこの制約を Model のバリデーション、Database の制約ともに考慮する必要はあるんだろうなとか。

スライドでも想定外の履歴データが作られていることがあり、原因調査に丸一日かかったという言及がされていました。基本的に INSERT されるはずなので、そこから問題となっているデータを特定するのに時間がかかるというのはあるんだろうなと。activerecord-bitemporal gem では visualizer 機能があり、レコードの履歴を可視化してくれるそうです。

有効期間の日付管理が timestamp だと時分秒の管理があるから、date 型に変更して運用容易性を担保したという話も興味深かったです。この部分で意図しないレコードが生まれるケースはありそうだなと思っていたところ、https://tech.smarthr.jp/entry/2025/09/12/115617 も拝見し、まさにその問題があったようですね。“履歴の一括出力後、Excelで適用日を編集するとExcelの仕様で時分秒の情報が「00:00:00」に丸められてしまう”、“例えば部署マスターの更新、並べ替え、削除、従業員部署の登録、更新などでは多数のモデルが同一トランザクションで更新されます。 このとき、適用日の時刻を固定して揃えないと、処理タイミングの僅かなズレによって適用日が秒未満の精度で異なった履歴が作成されてしまう” 、“同一適用日の更新において、社員番号と適用日の組み合わせでレコードを特定する際、ユーザーから秒未満を切り上げた日時を受け取り、秒未満を考慮して対象の履歴を探す” などなど、かなり負の側面を抱えていたようです。大変な移行だったようですが、とても意味のある移行だなと思いながら拝見しました。date 型だと unique 制約によって重複を弾きやすくなりますしね。

“履歴” を表現する1つの手段として Bitemporal Data Model を使ったリアルな声が公開されているのは、本当に嬉しいですね。とても参考になる話を聞けました。今後モデリングする際は、1つの手段として頭の片隅にインデックスを貼っておこうと思いました。

Kaigi on Rails 2025 に参加したタイミーのメンバー