負荷試験は、本番で想定するアクセス量をシステムに人工的にかけ、応答時間やエラー率が目標の範囲に収まるか、どこで限界を迎えるかを測る試験です。ここで扱うのはWebシステムや業務システムの負荷試験で、医療の運動負荷試験は対象外とします。
この記事では、試験の種類の使い分け、合否基準の書き方、アクセスログから業務の比率を拾って到着率で流すシナリオ設計を、そのまま動かせるk6のスクリプトで示します。後半では、本番相当環境をどこまで揃えるか、結果をキャパシティの見積もりへどう戻すか、受託開発で試験を作り込むべき条件まで整理します。
まとめ:負荷試験で先に決める合否基準・シナリオ・環境・結果の戻し先
負荷試験の成否は、ツールの選定より前の計画で決まります。実務で先に固めるのは次の4点で、上から順に決めると手戻りが出ません。
- 合否基準:平均応答時間ではなく、応答時間の95パーセンタイルとエラー率で書く。画面や処理ごとに値を分ける
- シナリオ:アクセスログから画面ごとの比率を拾い、仮想ユーザー数ではなく毎秒の到着件数で負荷を指定する
- 環境:インスタンス種別・設定値・データ件数は本番と揃え、台数と外部APIだけを縮小や代替の対象にする
- 結果の戻し先:1台あたりの上限処理量と、最初に張りついた資源をキャパシティの見積もりと監視のしきい値に書き戻す
試験は1台への小さな負荷から始め、全体構成での試験へ広げます。いきなり本番規模で流すと、どの層で詰まったのか切り分けられません。
負荷試験とは何を確かめる試験か 平均負荷からスパイクまでの種類の違い
「負荷試験」は1種類の試験ではありません。何を確かめたいかで、かける負荷の大きさと時間が変わります。目的を決めずに試験を始めると、終わってから「結局どの問いに答えたのか」が曖昧になります。
スモークから限界試験まで6種類の負荷の大きさと試験時間の目安
Grafana k6の公式ドキュメントLoad test typesは、負荷試験を6種類に分け、負荷の大きさと試験時間の目安を示しています。
| 種類 | 確かめること | 負荷 | 時間の目安 |
|---|---|---|---|
| スモーク | スクリプトが動くか | 低い | 数秒〜数分 |
| 平均負荷 | 通常時の性能 | 本番の平均 | 5〜60分 |
| ストレス | 平均を超えた時 | 平均より高い | 5〜60分 |
| 耐久(ソーク) | 長時間の安定性 | 平均 | 数時間 |
| スパイク | 急増への耐性 | 非常に高い | 数分 |
| 限界(ブレークポイント) | 容量の上限 | 壊れるまで増やす | 必要なだけ |
実務でまず回すのは、スモークと平均負荷の2つです。この2つが通らない状態でストレス試験をしても、原因が負荷なのか不具合なのか判別できません。耐久試験はメモリリークや接続の解放漏れのように時間が経ってから出る問題を拾うためのもので、リリース前に一度は数時間流してください。
性能試験やラッシュテストと呼び名が分かれる理由と試験範囲の違い
現場では「負荷試験」「負荷テスト」「性能試験」「ラッシュテスト」が混在します。負荷テストは負荷試験の言い換えで、中身は同じです。性能試験は負荷をかけない単体の処理時間の測定まで含む広い呼び名として使われることが多く、ラッシュテストは受付開始の瞬間のように短時間に集中するアクセスを再現する試験を指します。後者は上の表のスパイク試験にあたります。
用語の違いと、発注側から見たラッシュテストの目的はラッシュテストと負荷テストの違いを解説した記事で整理しています。見積書や試験計画書では、呼び名ではなく「どの種類の試験を、どの負荷で、何分流すか」を書くと認識のずれが残りません。
負荷試験の計画で決める性能目標と合否基準をp95とエラー率で書く手順
計画書で最初に埋めるのは、何を満たせば合格とするかの1行です。この行が無いまま試験をすると、結果のグラフを見ながら「たぶん大丈夫」と判断することになります。
平均応答時間ではなく95パーセンタイルとエラー率で合否を置く理由
平均応答時間は、一部の極端に遅いリクエストを薄めてしまいます。100件のうち94件が0.2秒、6件が4秒かかった場合、平均は約0.43秒で目標の0.5秒を満たしますが、p95は4秒です。20人に1人以上が4秒待たされています。95パーセンタイル(p95)は「全体の95%がこの時間内に返る」値で、遅い側の体験をそのまま数値に出せます。
エラー率も同時に基準に入れてください。過負荷のシステムは、遅くなる代わりにエラーを即座に返して応答時間を良く見せることがあります。k6のThresholdsのドキュメントは、合否基準をhttp_req_failed: ['rate<0.01'](エラー1%未満)やhttp_req_duration: ['p(95)<200'](p95が200ミリ秒未満)の形で書く例を示しています。基準を1つでも満たさなければ試験は失敗扱いになり、k6が返す終了コードは0以外です。
非機能要件の性能目標を負荷試験の合格条件へ写すときの換算の手順
要件定義書の性能目標は「画面の表示は3秒以内」のように画面単位で書かれていることが多く、そのままでは試験の基準になりません。1画面の表示で複数のAPIが呼ばれるなら、画面全体の3秒をAPIごとの持ち時間に割り振り、APIごとのp95の基準へ書き換えます。
処理の重さが違うものは基準を分けます。一覧表示と帳票出力に同じ0.3秒を課すと、帳票が常に不合格になるか、一覧の基準が甘くなるかのどちらかです。要件の6大項目を数値に落とす手順は非機能要件を数値化してk6の閾値テストにつなぐ記事にまとめています。目標値の根拠をSLOとして運用に引き継ぐ場合は、関連記事のSLOの解説も参考になります。
業務比率と到着率で組む負荷試験のシナリオ設計とk6スクリプトの書き方
シナリオは「誰が、どの画面を、どの比率で、どれだけの頻度で使うか」の再現です。ここがずれると、合否基準をどれだけ精密に書いても、本番とは別のシステムを測ったことになります。
アクセスログから画面ごとの比率と1分単位のピークを拾うシナリオの作り方
既存システムがあるなら、出発点はアクセスログです。ピークの日のログを1分単位で集計し、最も混んだ1分間のURLごとの件数を数えます。URLを画面や処理の単位にまとめると、たとえば「一覧表示70%、検索20%、登録10%」のような比率が出ます。
AWSのWell-Architected Framework 信頼性の柱 REL07-BP04も、リクエストの組み合わせは時間帯によって変わるため、複数の時間枠を確認して特定するよう求めています。朝の始業直後は参照が多く、夕方の締め前は登録が増えるといった偏りがある業務システムでは、ピークの時間帯ごとにシナリオを分けてください。新規システムでログが無い場合は、業務フローから1人あたりの操作回数を積み上げた仮定値で始め、公開後のログで作り直します。
仮想ユーザー数でなく到着率で負荷を指定するオープンモデルの考え方
負荷の指定方法は2つあります。仮想ユーザー(VU)の人数を固定し、各ユーザーが前のリクエストの完了を待ってから次を送る「クローズドモデル」と、応答の速さに関係なく毎秒決まった件数を送り込む「オープンモデル」です。
k6のOpen and closed modelsの解説によると、クローズドモデルではシステムが遅くなるほど次のリクエストの開始が遅れ、到着率が下がります。試験の文献でcoordinated omissionと呼ばれる問題です。本番の利用者はサーバーが遅いからといって来るのを待ってはくれません。目標が「毎秒50件を捌けるか」なら、到着率を固定するオープンモデルで組みます。k6ではconstant-arrival-rateとramping-arrival-rateの2つのexecutorがこれにあたります。
クローズドモデルが向くのは、同時ログイン数の上限やセッション数を確かめる試験です。問いが「何人まで同時に使えるか」なのか「毎秒何件まで捌けるか」なのかで選び分けてください。
業務比率を3つのシナリオに分けて到着率で流すk6スクリプトの実例
一覧70%、検索20%、登録10%の比率で、合計毎秒50件まで5分かけて上げ、20分維持するスクリプトです。毎秒50件と比率は説明用の仮定値で、実際は前の工程で集計した値に置き換えます。k6は2026年9月に公開された2.3系で書いています。
// load_test.js:業務比率ごとに到着率を割り当てて流す
import http from 'k6/http';
import { check } from 'k6';
const BASE = __ENV.BASE_URL; // 試験対象のURL(実行時に -e で渡す)
const PEAK_RPS = 50; // キャパシティ見積で出したピーク毎秒
function arrival(share, fn) {
const rate = Math.round(PEAK_RPS * share);
return {
executor: 'ramping-arrival-rate',
exec: fn,
startRate: 0,
timeUnit: '1s',
preAllocatedVUs: 50,
maxVUs: 300,
stages: [
{ target: rate, duration: '5m' }, // ランプアップ
{ target: rate, duration: '20m' }, // ピークを維持
{ target: 0, duration: '2m' }, // ランプダウン
],
};
}
export const options = {
scenarios: {
list: arrival(0.7, 'list'),
find: arrival(0.2, 'find'),
register: arrival(0.1, 'register'),
},
thresholds: {
http_req_failed: ['rate<0.01'],
'http_req_duration{scenario:list}': ['p(95)<300'],
'http_req_duration{scenario:find}': ['p(95)<800'],
'http_req_duration{scenario:register}': ['p(95)<1000'],
},
};
export function list() {
const res = http.get(`${BASE}/api/items?page=1`);
check(res, { 'status 200': (r) => r.status === 200 });
}
export function find() {
const res = http.get(`${BASE}/api/items?q=sample`);
check(res, { 'status 200': (r) => r.status === 200 });
}
export function register() {
const body = JSON.stringify({ name: `item-${__VU}-${__ITER}` });
const res = http.post(`${BASE}/api/items`, body, {
headers: { 'Content-Type': 'application/json' },
});
check(res, { 'status 201': (r) => r.status === 201 });
}
実行はk6 run -e BASE_URL=https://stg.example.com load_test.jsです。各シナリオのメトリクスにはk6がシナリオ名のタグを付けるため、{scenario:list}のように画面ごとの基準を書き分けられます。到着率で組むときは、思考時間をsleepで入れる必要はありません。利用者が画面を読んでいる時間は、毎秒の到着件数にすでに織り込まれています。
本番相当環境をどこまで揃えるかとデータ量・外部連携・負荷発生側の準備
AWSのREL07-BP04は、本番と同じ設定ではない環境での負荷試験を、避けるべきアンチパターンの最初に挙げています。とはいえ本番と同じ台数の環境を毎回用意すると、費用がかさむのが難点です。揃えるべき項目と縮小してよい項目を分けて考えます。
インスタンス種別と設定値は揃え台数は縮小してよい本番相当環境の線引き
判断の基準は「1台あたりの性能を変えるかどうか」です。1台の性能を変える項目は本番と揃え、台数のように後から掛け算で補正できる項目は縮小してかまいません。
| 項目 | 扱い | 理由 |
|---|---|---|
| インスタンス種別 | 揃える | 1台の上限が変わる |
| DBの種別と設定値 | 揃える | 接続数上限が変わる |
| 接続プール・スレッド数 | 揃える | 詰まる箇所が変わる |
| LB・CDN・WAF | 揃える | 経路の遅延が変わる |
| アプリサーバー台数 | 縮小可 | 台数で掛け算できる |
| 外部API | スタブ可 | 相手の規約と費用 |
台数を縮小した環境で測った結果を本番の台数へ掛け算できるのは、データベースが詰まっていない範囲に限られます。アプリサーバーを2台から8台にしてもデータベースは1台のままなので、最終的には本番と同じ台数の構成で一度は流してください。クラウドなら試験の間だけ本番規模の環境を立て、終わったら消せます。
データ件数とキャッシュの温まり方で結果が数倍ずれる検証環境の落とし穴
検証環境のデータベースに数千件しか入っていないと、テーブル全体がメモリに載り、本番の数百万件で起きる読み込みの遅さが再現されません。索引の効き方や実行計画も件数で変わるため、データは本番と同じ桁の件数を用意します。本番データを複製して使う場合は、氏名や連絡先などの個人情報を置き換えてから入れるか、件数と値の分布だけを本番に合わせた合成データを作ります。
キャッシュの状態もそろえる対象です。デプロイ直後の数分はアプリケーションやデータベースのキャッシュが空で、応答が遅く出ます。最初の数分を慣らし運転として集計から外すか、逆に「デプロイ直後にピークが来たら」という条件を別の試験として明示的に測るか、どちらかに決めておきます。
決済や認証など外部APIをスタブに置き換える範囲とクラウド事業者の規約
決済代行、SMS送信、地図、外部の認証基盤といった他社のAPIへ、そのまま負荷をかけてはいけません。相手のサービスに迷惑がかかるうえ、従量課金で費用が膨らみ、レート制限で自社の試験も止まります。固定の応答を一定の待ち時間つきで返すスタブに置き換え、待ち時間は本番の実測値に合わせます。
クラウド上の自社環境へ負荷をかける場合も、事業者の規約を確認してください。AWSのDDoS Simulation Testing Policyは、DDoS攻撃を模した試験はAWSが事前に承認したパートナー企業が実施することを条件にしています(2026年10月時点で4社)。業務の想定負荷を確かめる通常の試験とは別物ですが、攻撃に近い規模の負荷を狙う場合は、この規約の対象になるかを先に確かめます。
負荷を出す側が先に詰まっていないかを確かめるdropped_iterationsの見方
見落とされやすいのが、負荷を出す側のマシンの限界です。負荷生成のCPUやネットワークが先に詰まると、試験対象は余裕があるのに「毎秒50件を出せていない」状態になり、結果が実際より良く見えます。
到着率のexecutorでは、用意した仮想ユーザーが足りずに開始できなかった回数がdropped_iterationsとして集計結果に出ます。この値が0でないなら、目標の到着率を出せていません。maxVUsを増やすか、負荷生成のマシンを分けて増やします。試験中は試験対象と同じく、負荷生成側のCPU使用率も記録してください。
実行と結果の読み方 段階的に負荷を上げてボトルネックを切り分ける手順
準備が整ったら、小さく始めて広げます。1回の大きな試験で全部を確かめようとすると、詰まった原因を特定できず、試験をやり直すことになります。
1台への小さな負荷から全体構成へ広げるAWS推奨の4段階の進め方
AWSのREL07-BP04が示す実装の手順は、次の4段階です。
- 時間枠を変えながらリクエストの組み合わせを特定する
- 独自のコード、オープンソース、商用製品のいずれかで負荷生成の仕組みを用意する
- インスタンスやコンテナ1つ分の小さな容量に負荷をかける
- 本番にできるだけ近い環境で、大きな容量に負荷をかける
3つ目の段階で1台の上限を測っておくと、4つ目で全体構成の結果が台数の掛け算から外れたとき、原因が台数を増やしても伸びない層(データベースや共有のキャッシュ)にあると絞り込めます。各段階の前には、スモーク試験でスクリプトとデータが正しく動くかを数分で確かめます。
応答時間が折れ曲がる点で最初に張りついた資源を特定する際の観点
到着率を段階的に上げながら、p95の応答時間を横軸の負荷に対して並べると、ある負荷を境に急に伸び始める点が出ます。その直前が、その構成で目標を守れる上限です。上限の負荷で何が最初に張りついたかを、CPU、メモリ、データベースの接続数、ストレージのIOPS、外部APIのスタブの応答の順に確かめます。
資源ごとに使用率、飽和、エラーの3つを見ていく手順はUSEメソッドで資源のボトルネックを見つける手順に沿うと抜けが出ません。エラーが先に増え、応答時間はむしろ短くなる場合は、接続の上限に当たって即座に拒否されている可能性があります。応答時間だけを見て合格にしないでください。
負荷試験の結果をキャパシティ見積に戻して必要台数と監視値を更新する手順
負荷試験は、合否を出したところで終わりではありません。測った数値を見積もりと監視に書き戻して、初めて次の増設や障害の予防に効きます。
1台の上限処理量を見積もりの分母へ入れ直して台数を再計算する流れ
前章で測った「p95が目標内に収まる1台の上限」は、必要台数の計算の分母になる値です。将来のピーク毎秒をこの上限と余裕率で割ると台数が出ます。計算式と、平常時と1台停止時の2条件で台数を出すスクリプトはキャパシティプランニングでピーク負荷から必要台数と余裕率を見積もる手順で解説しています。
試験の結果で分母が変わったら、見積もりの入力値を更新し、試験の日付とアプリのバージョンを並べて記録します。アプリを改修すれば1台の上限は変わるため、大きな機能追加の後には同じシナリオで測り直してください。
試験で見つけた予兆指標を監視のしきい値とCIの回帰試験に残す方法
上限に近づいたときに最初に動いた指標は、本番の監視でアラートを出すしきい値の候補になります。たとえば応答時間より先にデータベースの接続数が上限の8割に達していたなら、その接続数も監視の対象です。EC2のAuto Scalingで、試験の結果を伸縮の条件やクォータの確認に落とす手順はAWSでアクセス集中対策を設計する手順の記事にあります。
シナリオのスクリプトは捨てずに、CIで定期的に流す回帰試験として残します。k6は基準を満たさないと0以外の終了コードで終わるため、平均負荷の短縮版を夜間に流せば、性能を落とす変更が入った日に気づけます。
受託開発で負荷試験を本格的に組む条件と簡易な確認で済ませてよい場面
すべてのシステムに、本番規模の環境を立てて数時間の試験を回す必要はありません。次のどれかに当てはまる場合は、試験計画書を作り、本番相当環境での試験を開発工程に組み込みます。
- ピークの日時が決まっている:チケット発売、受付開始、年度末の締め処理など、数分で平常の10倍以上が来る
- 止まると売上や業務が止まる:決済、受発注、医療や物流の現場業務
- データベースや外部APIなど、後から台数で増やせない資源が先に詰まる構成
- 既存システムの刷新で、旧システムと同じ性能を約束している
逆に、利用者が数百人規模の社内ツールで、アクセスの山が小さいシステムは、スモーク試験と平均負荷の試験を検証環境で1回ずつ流せば十分です。本番相当環境を組む費用のほうが、起きうる遅延の損失より大きくなります。この場合も、合否基準の1行とシナリオのスクリプトだけは残しておくと、利用者が増えたときに同じ条件で測り直せます。
試験環境の構築と性能の作り込みをシステム開発と同じ担当で進める理由
負荷試験で見つかる問題の多くは、データベースの索引、接続プールの大きさ、キャッシュの設計といった、アプリとインフラの境目にあります。試験だけを別の会社に任せると、原因の切り分けで双方の行き来が増え、修正と再試験の周期が長くなります。
本番相当環境の構築から、シナリオの作成、ボトルネックの改修、監視への組み込みまでをまとめて進めたい場合は、一創のインフラ構築(AWS・Google Cloud・Azure)で、試験の計画段階から相談できます。
よくある質問
システムの負荷試験について、検索で多い質問に答えます。
負荷試験と負荷テストに違いはありますか?
同じものを指します。日本語の文書では「試験」、開発の現場やツールの説明では「テスト」が多いという程度の違いです。性能試験やストレステストとの関係についても、区別して捉える必要があります。性能試験は負荷をかけない処理時間の測定まで含む広い呼び名として使われ、ストレステストは想定を超える負荷をかける負荷試験の1種類です。計画書では呼び名に頼らず、負荷の大きさと時間を数値で書いてください。
負荷試験はどのくらいの時間をかけて実施しますか?
実施にかける時間は、負荷試験の種類によって異なるものです。Grafana k6のドキュメントでは、平均負荷とストレスの試験が5〜60分、耐久試験が数時間、スパイク試験が数分を目安にしています。準備の期間も含めると、シナリオ作成と環境構築で1〜2週間、実行と改修と再試験で1〜2週間を見込む案件が多くなります。改修のたびに再試験が要るため、本番公開の直前ではなく、開発の中盤から計画に組み込んでください。
負荷試験は本番環境で実施してもよいですか?
公開前のシステムなら、本番環境そのもので試験するのが最も正確です。すでに利用者がいる本番環境では、試験の負荷で実際の利用者が遅延やエラーに巻き込まれるため、原則として避けます。どうしても必要な場合は、利用の少ない時間帯に、外部APIをスタブに切り替えたうえで、段階的に負荷を上げ、異常が出たら即座に止める手順を決めてから実施します。登録系の操作で作ったデータを後で消す手順も用意してください。
同時接続数は何人を想定すればよいですか?
同時接続数そのものではなく、ピーク時に毎秒何件のリクエストが来るかを先に決めるのが近道です。ログインしている利用者の多くは画面を読んでいて、サーバーに処理を投げていないためです。毎秒の件数は、1日の利用者数と1人あたりの操作回数、ピークの時間帯への集中度から計算できます。同時ログイン数の上限を確かめたい場合だけ、仮想ユーザー数を固定するクローズドモデルで別の試験を組みます。
負荷試験ツールはどれを選べばよいですか?
シナリオをコードで管理してCIで回したいならk6(JavaScript)かLocust(Python)、画面操作で組み立てたい、またはプラグインの多さを重視するならJMeterが候補になります。どれを選んでも、到着率で負荷を指定できるか、画面ごとに合否基準を書き分けられるかの2点を確かめてください。チームが普段書いている言語に合わせると、スクリプトの保守を開発者が引き取りやすくなります。
関連記事
- k6とは?Grafana k6の使い方とインストール手順・負荷テストの書き方【v2.3対応】:本記事のスクリプトを動かすk6の導入手順が分かります
- Locustとは?Pythonで書く負荷試験の使い方・ramp-up・分散実行【2.46対応】:同じシナリオをPythonで書き、負荷生成を分散させたい場合の手順です
- JMeterでHTTP/2負荷テストを行う方法|BlazeMeter HTTPプラグインの導入と設定【3.2対応】:JMeterでHTTP/2の通信を再現して試験する方法です
- 負荷テストツール比較|Web・CPU・ネットワーク別の無料ツールとWindowsでの実行手順:試験対象に合わせてツールを選ぶときの比較材料になります
- SLOとは?SLA・SLIとの違いと設定方法をわかりやすく解説:合否基準にした応答時間の目標を、運用の目標値として引き継ぐ方法です