開発チームのKPIとは、チームの状態を「速さ・安定性・品質・進み具合」の4つの面から数値で確かめるための指標です。 指標は数多くありますが、同時に追うのは各分類から1〜2個で足ります。Four Keysは、そのうち「速さ」と「安定性」を見るための指標の組です。

この記事では、30指標を計算式・単位・元データつきの一覧にし、Four Keysについてはデプロイ記録と障害記録のCSVから実際に値を出すPythonとSQLを、実行結果と一緒に載せます。

確認環境:Python 3.11.15、PostgreSQL 16.15(Linux)。指標の定義は dora.dev の公式ガイド(最終更新 2026年1月5日の版)と SPACE の原論文を 2026-10-06 に開いて確認しました。

この記事の結論

  • KPIは 速さ・安定性・品質・進み具合 の4分類から各1〜2個に絞ると、片方だけが良くなる偏りに気づけます。
  • Four Keysは「速さ」と「安定性」を見る指標で、品質や進み具合は別の指標で補います。
  • dora.dev の現在の定義は5指標です(デプロイの手戻り率が加わり、復旧時間の呼び名が変わりました)。
  • 時間の指標は平均ではなく中央値で読みます。今回のデータでは平均21.3時間に対し中央値は8.0時間でした。
  • 数値は同じチーム・同じサービスの推移として読み、目標値そのものにしないのが公式ガイドの勧めです。

開発チームのKPIの早見表

分類 何を確かめるか まず選ぶ指標 元データ
速さ 変更が利用者に届くまでの早さ デプロイ頻度、変更のリードタイム コミット履歴、デプロイ記録
安定性 届けた変更が安定して動いているか 変更失敗率、失敗したデプロイの復旧時間 デプロイ記録、障害記録
品質 作ったものの出来 本番流出率、CIの成功率 バグ票、CIの実行履歴
進み具合 計画に対してどこまで来たか 計画に対する完了率、SPI スプリントの記録、WBS

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「開発チームのKPI一覧|指標の計算式とFour Keysの測り方」

KPI 30指標の一覧(計算式・単位・元データ)

分類ごとに、速さ8・安定性8・品質7・進み具合7の合計30指標です。

No. 分類 指標名 計算式 単位 元データ 読み違えやすい点
1 速さ デプロイ頻度 デプロイ回数 ÷ 期間 回/週 デプロイ記録 回数そのものを目標にすると中身のない小分けが増える
2 速さ 変更のリードタイム (本番デプロイ時刻 − コミット時刻)の中央値 時間 コミット履歴・デプロイ記録 平均は長い1件に引っ張られるので中央値で見る
3 速さ サイクルタイム (完了日時 − 着手日時)の中央値 日 チケットの状態遷移 「着手」の定義が人によって違うと比べられない
4 速さ レビュー待ち時間 (最初のレビュー時刻 − レビュー依頼時刻)の中央値 時間 プルリクエスト 夜間・休日を含めるかを先に決める
5 速さ マージまでの時間 (マージ時刻 − プルリクエスト作成時刻)の中央値 時間 プルリクエスト 変更行数が多いほど長くなるので行数と併せて見る
6 速さ CIの所要時間 (パイプライン終了時刻 − 開始時刻)の中央値 分 CIの実行履歴 キャッシュの有無で大きく変わる
7 速さ スループット 期間内に完了したチケット数 件/週 チケット チケットの粒度がそろっていないと増減に意味が出ない
8 速さ 仕掛かり数(WIP) 作業中の状態にあるチケット数 件 カンバン 絶対数ではなく人数に対する比で見る
9 安定性 変更失敗率 すぐに手当てが必要になったデプロイ数 ÷ デプロイ数 × 100 % デプロイ記録・障害記録 分母が小さい週は1件で大きく動く
10 安定性 失敗したデプロイの復旧時間 (復旧時刻 − デプロイ時刻)の中央値 時間 障害記録 起点を検知時刻にすると短く見える
11 安定性 デプロイの手戻り率 障害対応のための計画外デプロイ数 ÷ デプロイ数 × 100 % デプロイ記録 「計画外」の判定ルールを先に決める
12 安定性 稼働率 (対象時間 − 停止時間)÷ 対象時間 × 100 % 監視の記録 計画停止を含めるかどうかで値が変わる
13 安定性 MTBF(平均故障間隔) 稼働時間の合計 ÷ 障害件数 時間 障害記録 件数が少ない期間は振れ幅が大きい
14 安定性 MTTR(平均復旧時間) 復旧にかかった時間の合計 ÷ 障害件数 時間 障害記録 デプロイ起因以外の障害も含む点が上の復旧時間と違う
15 安定性 エラー予算の消費率 実際のエラー数 ÷ 許容できるエラー数 × 100 % SLOの定義・監視の記録 期間の途中では消費の速さで読む
16 安定性 重大度別の障害件数 期間内の障害件数(重大度ごと) 件/月 障害記録 報告しやすい雰囲気になるほど件数は増える
17 品質 バグ密度 バグ件数 ÷ 規模 件/KLOC バグ票・行数 規模の数え方(新規・改修)をそろえる
18 品質 本番流出率 リリース後に見つかったバグ数 ÷ 全バグ数 × 100 % バグ票(発見工程つき) 発見工程の記入もれがあると低く出る
19 品質 テストカバレッジ テストで実行された行数 ÷ 実行可能な行数 × 100 % カバレッジ計測ツール 高い値は「通った」ことを示し「確かめた」ことまでは示さない
20 品質 CIの成功率 成功したパイプライン数 ÷ 実行数 × 100 % CIの実行履歴 再実行で通した分を成功に数えると高く出る
21 品質 不安定なテストの割合 同じコードで結果が変わったテスト数 ÷ テスト数 × 100 % CIの実行履歴 再実行の記録が残る設定にしておく
22 品質 レビュー指摘密度 指摘件数 ÷ レビュー対象の規模 件/KLOC レビュー記録 軽微な指摘と設計上の指摘を分けて数える
23 品質 バグの再オープン率 再オープンされた件数 ÷ クローズ件数 × 100 % バグ票の状態遷移 確認待ちで戻した分を除くかを決める
24 進み具合 ベロシティ スプリントで完了したストーリーポイントの合計 pt/スプリント スプリントの記録 チーム間の比較には使えない(ポイントの基準が違う)
25 進み具合 計画に対する完了率 完了したポイント ÷ 計画したポイント × 100 % スプリントの記録 毎回100%なら計画が控えめな可能性がある
26 進み具合 残作業量 未完了の作業のポイント(または時間)の合計 pt バックログ 途中で追加された作業を別の線で描く
27 進み具合 SPI(スケジュール効率) EV ÷ PV 比率 WBS・進捗の記録 終盤は必ず1に近づくので序盤〜中盤で読む
28 進み具合 CPI(コスト効率) EV ÷ AC 比率 WBS・工数の記録 EVの計上ルールで値が変わる
29 進み具合 見積もり精度 実際の工数 ÷ 見積もり工数 × 100 % 見積もり・工数の記録 100%より上は見積もり超過を表す
30 進み具合 計画外作業の割合 計画外に入った作業の工数 ÷ 全工数 × 100 % チケットのラベル・工数の記録 ラベルを付ける基準をそろえる

バグ密度・レビュー指摘密度の基準値の決め方、SPI・CPIの途中計算は、それぞれ品質指標とEVMの話題として独立した内容になるため、この一覧では式だけを載せています。

表計算ソフトに貼る場合は、次のタブ区切りをそのままコピーしてください。

分類  指標名 計算式 単位  元データ    読み違えやすい点
速さ  デプロイ頻度  デプロイ回数 ÷ 期間 回/週 デプロイ記録  回数そのものを目標にすると中身のない小分けが増える
速さ  変更のリードタイム   (本番デプロイ時刻 − コミット時刻)の中央値 時間  コミット履歴・デプロイ記録   平均は長い1件に引っ張られるので中央値で見る
速さ  サイクルタイム (完了日時 − 着手日時)の中央値   日   チケットの状態遷移   「着手」の定義が人によって違うと比べられない
速さ  レビュー待ち時間    (最初のレビュー時刻 − レビュー依頼時刻)の中央値  時間  プルリクエスト 夜間・休日を含めるかを先に決める
速さ  マージまでの時間    (マージ時刻 − プルリクエスト作成時刻)の中央値   時間  プルリクエスト 変更行数が多いほど長くなるので行数と併せて見る
速さ  CIの所要時間 (パイプライン終了時刻 − 開始時刻)の中央値 分   CIの実行履歴 キャッシュの有無で大きく変わる
速さ  スループット  期間内に完了したチケット数   件/週 チケット    チケットの粒度がそろっていないと増減に意味が出ない
速さ  仕掛かり数(WIP)  作業中の状態にあるチケット数  件   カンバン    絶対数ではなく人数に対する比で見る
安定性 変更失敗率   すぐに手当てが必要になったデプロイ数 ÷ デプロイ数 × 100    %   デプロイ記録・障害記録 分母が小さい週は1件で大きく動く
安定性 失敗したデプロイの復旧時間   (復旧時刻 − デプロイ時刻)の中央値 時間  障害記録    起点を検知時刻にすると短く見える
安定性 デプロイの手戻り率   障害対応のための計画外デプロイ数 ÷ デプロイ数 × 100  %   デプロイ記録  「計画外」の判定ルールを先に決める
安定性 稼働率 (対象時間 − 停止時間)÷ 対象時間 × 100   %   監視の記録   計画停止を含めるかどうかで値が変わる
安定性 MTBF(平均故障間隔)    稼働時間の合計 ÷ 障害件数  時間  障害記録    件数が少ない期間は振れ幅が大きい
安定性 MTTR(平均復旧時間)    復旧にかかった時間の合計 ÷ 障害件数 時間  障害記録    デプロイ起因以外の障害も含む点が上の復旧時間と違う
安定性 エラー予算の消費率   実際のエラー数 ÷ 許容できるエラー数 × 100   %   SLOの定義・監視の記録    期間の途中では消費の速さで読む
安定性 重大度別の障害件数   期間内の障害件数(重大度ごと) 件/月 障害記録    報告しやすい雰囲気になるほど件数は増える
品質  バグ密度    バグ件数 ÷ 規模   件/KLOC  バグ票・行数  規模の数え方(新規・改修)をそろえる
品質  本番流出率   リリース後に見つかったバグ数 ÷ 全バグ数 × 100 %   バグ票(発見工程つき) 発見工程の記入もれがあると低く出る
品質  テストカバレッジ    テストで実行された行数 ÷ 実行可能な行数 × 100 %   カバレッジ計測ツール  高い値は「通った」ことを示し「確かめた」ことまでは示さない
品質  CIの成功率  成功したパイプライン数 ÷ 実行数 × 100 %   CIの実行履歴 再実行で通した分を成功に数えると高く出る
品質  不安定なテストの割合  同じコードで結果が変わったテスト数 ÷ テスト数 × 100  %   CIの実行履歴 再実行の記録が残る設定にしておく
品質  レビュー指摘密度    指摘件数 ÷ レビュー対象の規模    件/KLOC  レビュー記録  軽微な指摘と設計上の指摘を分けて数える
品質  バグの再オープン率   再オープンされた件数 ÷ クローズ件数 × 100   %   バグ票の状態遷移    確認待ちで戻した分を除くかを決める
進み具合    ベロシティ   スプリントで完了したストーリーポイントの合計  pt/スプリント    スプリントの記録    チーム間の比較には使えない(ポイントの基準が違う)
進み具合    計画に対する完了率   完了したポイント ÷ 計画したポイント × 100   %   スプリントの記録    毎回100%なら計画が控えめな可能性がある
進み具合    残作業量    未完了の作業のポイント(または時間)の合計   pt  バックログ   途中で追加された作業を別の線で描く
進み具合    SPI(スケジュール効率)   EV ÷ PV 比率  WBS・進捗の記録   終盤は必ず1に近づくので序盤〜中盤で読む
進み具合    CPI(コスト効率)  EV ÷ AC 比率  WBS・工数の記録   EVの計上ルールで値が変わる
進み具合    見積もり精度  実際の工数 ÷ 見積もり工数 × 100    %   見積もり・工数の記録  100%より上は見積もり超過を表す
進み具合    計画外作業の割合    計画外に入った作業の工数 ÷ 全工数 × 100    %   チケットのラベル・工数の記録  ラベルを付ける基準をそろえる

KGI・KPI・OKRの違い

用語 何を表すか 開発チームでの例 見直す間隔
KGI 最終的に到達したい結果 備品予約システムの月間利用者を2,000人にする 半年〜1年
KPI KGIに向かう途中の状態を継続して測る数値 変更のリードタイム、変更失敗率 週〜月
OKR 期間を区切った挑戦的な目標(O)と、その到達を示す数値(KR) O: 予約を迷わず終えられるようにする/KR: 予約完了までの画面数を5から3にする 四半期

KPIは「続けて見る体温計」、OKRは「この四半期に動かしたい数値」です。KPIのうち今期に大きく変えたいものをKRに取り上げる、という関係で併用できます。

Four Keysの現在の定義(dora.dev)

dora.dev の公式ガイド「DORA’s software delivery performance metrics」では、ソフトウェアデリバリーの指標をスループット3つ・不安定さ2つの計5指標として説明しています。もともとの4指標から5指標へ変わったこと、MTTRから「Failed deployment recovery time」へ呼び名が変わったことも同じページに書かれています。

公式の区分 現在の指標名(dora.dev) 公式の定義(要約) よく使われる日本語の呼び名 以前の呼び名
スループット Change lead time 変更がバージョン管理にコミットされてから本番にデプロイされるまでの時間 変更のリードタイム Lead time for changes
スループット Deployment frequency 一定期間のデプロイ回数、またはデプロイの間隔 デプロイ頻度 Deployment frequency
スループット Failed deployment recovery time うまくいかず、すぐに手当てが必要になったデプロイから復旧するまでの時間 復旧時間、サービス復元時間 Time to restore service、MTTR
不安定さ Change fail rate デプロイ後すぐに手当てが必要になったデプロイの割合 変更失敗率、変更障害率 Change failure rate
不安定さ Deployment rework rate 本番の障害を受けて行った計画外デプロイの割合 デプロイの手戻り率 (追加された指標)

同じページには、使うときの注意点も挙げられています。

公式ガイドの注意点 内容
指標を目標にする 「年末までに全アプリケーションを1日複数回デプロイ」のような宣言は、数値合わせを招きやすい
1つの指標だけを見る 複雑な仕組みを1つの数値で測ろうとしない
性質の違うものを比べる モバイルアプリとメインフレームのように大きく違うアプリケーション同士の比較は誤解を生む
持ち主を分ける 5指標すべてを開発・運用・リリースの各チームで共有する
競い合う ほかのチームとの競争ではなく、自分たちの改善に使う
計測そのものに力を入れすぎる 計測の仕組みづくりより改善を優先する

指標はアプリケーションまたはサービスの単位で当てはめる、とも書かれています。なお、このガイドのページには水準(Elite/High など)の数値表は載っていません。水準と比べたい場合は、その年のDORAレポート本体で年版を確かめてから使ってください。

CSVからFour Keysを計算する(Python)

架空の備品予約システムの4週間分(2026-09-07〜2026-10-04)の記録を使います。必要なのは次の3つのCSVです。

ファイル 1行が表すもの 列
deploys.csv 本番デプロイ1回 deploy_id、deployed_at、kind(planned=計画どおり/rework=障害対応の計画外)、failed(1=すぐに手当てが必要になった)
changes.csv 変更(コミット)1件 change_id、committed_at、deploy_id(どのデプロイで本番に出たか)
incidents.csv デプロイが原因の障害1件 incident_id、deploy_id、detected_at、restored_at

deploys.csv

deploy_id,deployed_at,kind,failed
D001,2026-09-07 15:10,planned,0
D002,2026-09-08 11:30,planned,0
D003,2026-09-09 16:45,planned,1
D004,2026-09-09 18:20,rework,0
D005,2026-09-11 14:00,planned,0
D006,2026-09-14 10:15,planned,0
D007,2026-09-15 15:40,planned,0
D008,2026-09-16 13:05,planned,0
D009,2026-09-17 17:30,planned,1
D010,2026-09-18 09:50,rework,0
D011,2026-09-21 11:00,planned,0
D012,2026-09-22 16:20,planned,0
D013,2026-09-24 14:35,planned,0
D014,2026-09-25 15:10,planned,0
D015,2026-09-28 10:40,planned,0
D016,2026-09-29 13:25,planned,1
D017,2026-09-29 14:10,rework,0
D018,2026-09-30 16:00,planned,0
D019,2026-10-01 11:45,planned,0
D020,2026-10-02 15:30,planned,0

incidents.csv

incident_id,deploy_id,detected_at,restored_at
I001,D003,2026-09-09 17:05,2026-09-09 18:20
I002,D009,2026-09-17 18:15,2026-09-18 09:50
I003,D016,2026-09-29 13:35,2026-09-29 14:10

changes.csv

change_id,committed_at,deploy_id
C001,2026-09-05 13:30,D001
C002,2026-09-06 13:10,D001
C003,2026-09-07 07:10,D001
C004,2026-09-08 03:05,D002
C005,2026-09-09 11:05,D003
C006,2026-09-09 17:10,D004
C007,2026-09-11 08:50,D005
C008,2026-09-11 05:50,D005
C009,2026-09-11 11:00,D005
C010,2026-09-11 09:50,D006
C011,2026-09-13 14:05,D006
C012,2026-09-14 06:35,D006
C013,2026-09-13 14:00,D007
C014,2026-09-15 07:00,D007
C015,2026-09-13 14:30,D007
C016,2026-09-16 10:05,D008
C017,2026-09-16 07:25,D008
C018,2026-09-16 15:20,D009
C019,2026-09-14 17:30,D009
C020,2026-09-18 08:10,D010
C021,2026-09-20 08:50,D011
C022,2026-09-22 08:20,D012
C023,2026-09-19 16:10,D012
C024,2026-09-22 13:10,D012
C025,2026-09-24 09:35,D013
C026,2026-09-25 11:30,D014
C027,2026-09-27 08:40,D015
C028,2026-09-28 16:45,D016
C029,2026-09-29 10:25,D016
C030,2026-09-29 05:25,D016
C031,2026-09-29 12:30,D017
C032,2026-09-25 16:00,D018
C033,2026-10-01 06:45,D019
C034,2026-10-01 08:20,D019
C035,2026-10-01 12:50,D020
C036,2026-10-02 10:30,D020

計算するコード

標準ライブラリだけで動きます。3つのCSVと同じフォルダに dora.py として保存し、python3 dora.py で実行します。

import csv
from datetime import datetime, date
from statistics import median

FMT = "%Y-%m-%d %H:%M"
PERIOD_START, PERIOD_END = date(2026, 9, 7), date(2026, 10, 4)   # 4週間(28日)

def load(path):
    with open(path, encoding="utf-8", newline="") as f:
        return list(csv.DictReader(f))

def hours(a, b):
    return (datetime.strptime(b, FMT) - datetime.strptime(a, FMT)).total_seconds() / 3600

deploys = load("deploys.csv")
changes = load("changes.csv")
incidents = load("incidents.csv")
deployed_at = {d["deploy_id"]: d["deployed_at"] for d in deploys}

# 1. デプロイ頻度
days = (PERIOD_END - PERIOD_START).days + 1
weeks = days / 7
active_days = len({d["deployed_at"][:10] for d in deploys})
print(f"期間: {PERIOD_START} 〜 {PERIOD_END}({days}日)")
print(f"デプロイ頻度: {len(deploys)}回 / {weeks:.0f}週 = 週{len(deploys) / weeks:.1f}回"
      f"(デプロイした日 {active_days}日)")

# 2. 変更のリードタイム(コミット → 本番デプロイ)
lead = sorted(hours(c["committed_at"], deployed_at[c["deploy_id"]]) for c in changes)
print(f"変更のリードタイム: 中央値 {median(lead):.1f}時間 / 平均 {sum(lead) / len(lead):.1f}時間"
      f" / 最大 {lead[-1]:.1f}時間(変更 {len(lead)}件)")

# 3. 変更失敗率(すぐに手当てが必要になったデプロイの割合)
failed = [d for d in deploys if d["failed"] == "1"]
print(f"変更失敗率: {len(failed)} / {len(deploys)} = {len(failed) / len(deploys):.1%}")

# 4. 失敗したデプロイの復旧時間(デプロイ → 復旧)
rec = sorted(hours(deployed_at[i["deploy_id"]], i["restored_at"]) for i in incidents)
print(f"復旧時間: 中央値 {median(rec):.2f}時間 / 平均 {sum(rec) / len(rec):.2f}時間"
      f" / 最大 {rec[-1]:.2f}時間({len(rec)}件)")

# 5. デプロイの手戻り率(障害対応のための計画外デプロイの割合)
rework = [d for d in deploys if d["kind"] == "rework"]
print(f"デプロイの手戻り率: {len(rework)} / {len(deploys)} = {len(rework) / len(deploys):.1%}")

# 週ごとの内訳
print("\n週の開始日  デプロイ  失敗  手戻り  リードタイム中央値(h)")
for w in range(int(weeks)):
    ds = [d for d in deploys
          if (datetime.strptime(d["deployed_at"], FMT).date() - PERIOD_START).days // 7 == w]
    ids = {d["deploy_id"] for d in ds}
    lt = [hours(c["committed_at"], deployed_at[c["deploy_id"]]) for c in changes if c["deploy_id"] in ids]
    monday = date.fromordinal(PERIOD_START.toordinal() + 7 * w)
    print(f"{monday}  {len(ds):>7}  {sum(d['failed'] == '1' for d in ds):>4}"
          f"  {sum(d['kind'] == 'rework' for d in ds):>6}  {median(lt):>10.1f}")

実行結果

期間: 2026-09-07 〜 2026-10-04(28日)
デプロイ頻度: 20回 / 4週 = 週5.0回(デプロイした日 18日)
変更のリードタイム: 中央値 8.0時間 / 平均 21.3時間 / 最大 120.0時間(変更 36件)
変更失敗率: 3 / 20 = 15.0%
復旧時間: 中央値 1.58時間 / 平均 6.22時間 / 最大 16.33時間(3件)
デプロイの手戻り率: 3 / 20 = 15.0%

週の開始日  デプロイ  失敗  手戻り  リードタイム中央値(h)
2026-09-07        5     1       1         8.0
2026-09-14        5     1       1        20.2
2026-09-21        4     0       0         6.5
2026-09-28        6     1       1         6.5

結果の読み方

指標 値 読み方
デプロイ頻度 週5.0回 28日のうち18日でデプロイ。平日はほぼ毎日届けている
変更のリードタイム 中央値8.0時間 半分の変更はコミットから8時間以内に本番へ。最大は120時間で、長く待った変更が少数ある
変更失敗率 15.0% 20回のうち3回ですぐに手当てが必要になった
復旧時間 中央値1.58時間 3件のうち1件は夜をまたいで16.33時間。件数が少ないので最大値も併記する
デプロイの手戻り率 15.0% 20回のうち3回が障害対応のための計画外デプロイ

週ごとの内訳では、第2週だけリードタイムの中央値が20.2時間に伸びています。期間全体の値だけでは見えない変化なので、全体の値と週ごとの推移を並べて見ると改善のきっかけを見つけやすくなります。

同じ集計をSQLで行う(PostgreSQL)

記録がデータベースにある場合は、SQLだけで同じ値を出せます。psql で次のファイルを流します(DB名は appdb に置き換えて表記しています)。

psql -d appdb -f dora.sql
CREATE TABLE deploys   (deploy_id text PRIMARY KEY, deployed_at timestamp NOT NULL,
                        kind text NOT NULL, failed int NOT NULL);
CREATE TABLE changes   (change_id text PRIMARY KEY, committed_at timestamp NOT NULL,
                        deploy_id text NOT NULL REFERENCES deploys);
CREATE TABLE incidents (incident_id text PRIMARY KEY, deploy_id text NOT NULL REFERENCES deploys,
                        detected_at timestamp NOT NULL, restored_at timestamp NOT NULL);
\copy deploys   FROM 'deploys.csv'   WITH (FORMAT csv, HEADER true)
\copy changes   FROM 'changes.csv'   WITH (FORMAT csv, HEADER true)
\copy incidents FROM 'incidents.csv' WITH (FORMAT csv, HEADER true)

-- 期間全体の5指標
WITH d AS (
  SELECT count(*) AS deploys,
         count(*) FILTER (WHERE failed = 1)       AS failed,
         count(*) FILTER (WHERE kind = 'rework')  AS rework
  FROM deploys
  WHERE deployed_at >= DATE '2026-09-07' AND deployed_at < DATE '2026-10-05'
), l AS (
  SELECT percentile_cont(0.5) WITHIN GROUP (
           ORDER BY extract(epoch FROM dp.deployed_at - c.committed_at) / 3600) AS lead_h
  FROM changes c JOIN deploys dp USING (deploy_id)
), r AS (
  SELECT percentile_cont(0.5) WITHIN GROUP (
           ORDER BY extract(epoch FROM i.restored_at - dp.deployed_at) / 3600) AS recovery_h
  FROM incidents i JOIN deploys dp USING (deploy_id)
)
SELECT d.deploys,
       round(d.deploys / 4.0, 1)                    AS per_week,
       round(l.lead_h::numeric, 1)                  AS lead_median_h,
       round(100.0 * d.failed / d.deploys, 1)       AS fail_rate_pct,
       round(r.recovery_h::numeric, 2)              AS recovery_median_h,
       round(100.0 * d.rework / d.deploys, 1)       AS rework_rate_pct
FROM d, l, r;

-- 週ごとの内訳
SELECT date_trunc('week', dp.deployed_at)::date AS week_start,
       count(DISTINCT dp.deploy_id)                                    AS deploys,
       count(DISTINCT dp.deploy_id) FILTER (WHERE dp.failed = 1)       AS failed,
       count(DISTINCT dp.deploy_id) FILTER (WHERE dp.kind = 'rework')  AS rework,
       round(percentile_cont(0.5) WITHIN GROUP (
           ORDER BY extract(epoch FROM dp.deployed_at - c.committed_at) / 3600)::numeric, 1) AS lead_median_h
FROM deploys dp JOIN changes c USING (deploy_id)
GROUP BY 1 ORDER BY 1;

実行結果(集計の2つのSELECT)

 deploys | per_week | lead_median_h | fail_rate_pct | recovery_median_h | rework_rate_pct 
---------+----------+---------------+---------------+-------------------+-----------------
      20 |      5.0 |           8.0 |          15.0 |              1.58 |            15.0
(1 row)

 week_start | deploys | failed | rework | lead_median_h 
------------+---------+--------+--------+---------------
 2026-09-07 |       5 |      1 |      1 |           8.0
 2026-09-14 |       5 |      1 |      1 |          20.2
 2026-09-21 |       4 |      0 |      0 |           6.5
 2026-09-28 |       6 |      1 |      1 |           6.5
(4 rows)

Pythonの結果と一致しました。中央値は percentile_cont(0.5) WITHIN GROUP で求めています。期間を変えるときは、最初の WITH 句と同じ条件を changes・incidents 側の集計にも付けてください。

Four KeysとSPACEの違い

SPACEは2021年にACM Queueで発表された、開発者の生産性を5つの側面からとらえる枠組みです。

比べる点 Four Keys(DORAの指標) SPACE
見る対象 ソフトウェアを届ける流れ(デリバリー) 開発者とチームの生産性全体
中身 決まった指標(現在は5つ) 5つの側面(満足度と健やかさ/パフォーマンス/活動量/コミュニケーションと協働/効率とフロー)。指標は自分たちで選ぶ
単位 アプリケーション・サービス 個人・チーム・組織
データの種類 デプロイ記録や障害記録などシステムの記録 システムの記録に加えてアンケートなど本人の感じ方
選び方の指針 5指標を一緒に見る 複数の側面から選ぶ(原論文では少なくとも3つの側面を勧めている)
こういうとき 選ぶもの
リリースの流れの詰まりを見つけたい Four Keys
デプロイ記録や障害記録がすでにある Four Keys
数値は良いのにチームが疲れている気がする SPACE(満足度、効率とフローの側面を追加)
活動量(コミット数など)だけで評価されそうになっている SPACE(別の側面を2つ以上組み合わせる)
まだ本番リリースがない開発の序盤 進み具合と品質の指標から始め、リリース後にFour Keysを加える

チームの状況別:どの指標から始めるか

チームの状況 最初に選ぶ指標(2〜4個) 理由
本番リリース前の新規開発 計画に対する完了率、残作業量、CIの成功率 デプロイ記録がまだ無いので、進み具合と品質から見る
月に1〜2回リリースしている 変更のリードタイム、変更失敗率 件数が少ないので月単位で集計し、1件ごとの中身も読む
毎日のようにリリースしている デプロイ頻度、変更のリードタイム、変更失敗率、復旧時間 件数が十分あり、週ごとの推移が意味を持つ
障害対応に時間を取られている 復旧時間、デプロイの手戻り率、計画外作業の割合 安定性の指標と、開発時間への影響を一緒に見る
レビューで作業が止まりがち レビュー待ち時間、マージまでの時間、仕掛かり数 リードタイムのどの区間が長いかを分けて見る
運用・保守が中心 稼働率、MTTR、重大度別の障害件数 デプロイ起因以外の障害も含めて見る
見積もりと結果のずれが大きい 見積もり精度、計画外作業の割合 ずれの原因が見積もりか割り込みかを分ける

絞るときの手順は次の3つです。

  1. いま困っていることを1文で書く(例:リリースのたびに手直しが入る)。
  2. 上の表から、その状況に合う指標を2〜4個選ぶ。速さだけ、安定性だけに偏らないようにする。
  3. 元データが今ある記録で取れるかを確かめ、取れない指標は記録のしかたを決めてから始める。

確かめて分かったこと

  • 平均と中央値で値が大きく違いました。 変更のリードタイムは平均21.3時間、中央値8.0時間です。120時間かかった1件が平均を押し上げています。
  • SQLで変更の表と結合したまま数えると、デプロイ回数が増えます。 deploys と changes を結合して count で数えると36になり(本来は20)、変更失敗率も16.7%と出ました(本来は15.0%)。結合した集計では count(DISTINCT deploy_id) を使います。
  • 復旧時間は起点で値が変わります。 デプロイ時刻を起点にすると中央値1.58時間、障害の検知時刻を起点にすると1.25時間でした。チーム内でどちらにするかを決めて書いておきます。
  • 週単位の変更失敗率は1件で大きく動きます。 週のデプロイは4〜6回なので、1件で17〜25%になります。件数が少ない間は月単位で集計します。
  • dora.dev の現在のガイドは5指標です。 復旧時間は「スループット」の側に分類されていて、「安定性の指標」として紹介される一般的な説明とは区分が違います。
  • 同じガイドのページに水準の数値表はありません。 水準の数値を引用するときは、どの年のレポートかを添えます。

つまずきやすい点と整え方

つまずきやすい点 こうするとよい
指標を10個以上並べて、どれも見なくなる 4分類から各1〜2個に絞り、ほかは「必要になったら見る」一覧に回す
デプロイ頻度だけを上げようとする 変更失敗率と必ず組にして見る
チーム同士を数値で比べる 同じチーム・同じサービスの前月との差で読む
「デプロイ」「障害」の数え方が人で違う 何を1回・1件と数えるかを1行で定義して記録の先頭に書く
手で集計して続かなくなる デプロイ時に1行追記する仕組みにし、集計は上のコードやSQLで毎週同じ形で出す

よくある質問

Q. Four Keysとは何ですか? A. ソフトウェアを届ける流れの速さと安定性を測る指標の組です。もとは4指標で、dora.dev の現在のガイドではデプロイの手戻り率を加えた5指標として説明されています。

Q. KPIとKGIの違いは何ですか? A. KGIは最終的に到達したい結果、KPIはそこへ向かう途中の状態を継続して測る数値です。開発チームでは、利用者数などのKGIに対して、リードタイムや変更失敗率をKPIに置きます。

Q. 変更のリードタイムはどこからどこまでを測りますか? A. 変更がバージョン管理にコミットされてから本番にデプロイされるまでです。チケットの起票から測る値は「サイクルタイム」など別の指標として分けておくと混ざりません。

Q. デプロイの記録が取れないときはどうすればよいですか? A. デプロイのたびに日時・種別・結果の1行をCSVに追記するところから始められます。この記事の deploys.csv と同じ4列があれば、デプロイ頻度・変更失敗率・手戻り率の3つは計算できます。

Q. KPIはいくつ設定すればよいですか? A. 同時に追うのは4〜8個が目安です。4分類から各1〜2個を選ぶと、速さと安定性、品質と進み具合の両方を見られます。

まとめ

  • KPIは 速さ・安定性・品質・進み具合 の4分類から各1〜2個に絞る。
  • Four Keysは速さと安定性の指標。dora.dev の現在の定義は5指標で、復旧時間の呼び名は Failed deployment recovery time。
  • 時間の指標は中央値で読む。平均は長い1件に引っ張られる。
  • デプロイ記録・変更の記録・障害記録の3つのCSVがあれば、PythonでもSQLでも同じ値を出せる。
  • SQLで結合して数えるときは count(DISTINCT) を使う。
  • 数値は同じチームの推移として読み、目標値そのものにしない。
  • 開発者の満足度や協働まで見たいときはSPACEの側面を足す。

参考・出典

  • DORA「DORA’s software delivery performance metrics」 https://dora.dev/guides/dora-metrics-four-keys/ (2026-10-06 確認)
  • Nicole Forsgren ほか「The SPACE of Developer Productivity」ACM Queue vol. 19, no. 1 https://queue.acm.org/detail.cfm?id=3454124 (2026-10-06 確認)

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「開発チームのKPI一覧|指標の計算式とFour Keysの測り方」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?