docs: API負荷試験の事前調査結果と試験計画を追加 - #435
Conversation
📝 WalkthroughWalkthroughSeeFT APIのエンドポイント調査、本番構成、負荷シナリオ、k6試験手順、実測結果、判定基準、リスク、後続作業を文書化しています。 ChangesAPI負荷試験計画
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/development/load-test-plan.md`:
- Line 3:
「作成日」の日付を現在の実際の作成日である2026年7月16日に修正するか、2026年7月17日が予定日であることが明確に分かる表記へ変更してください。
- Line 220: Remove the concrete production IP address from the documentation
sentence near the production configuration reference, and describe the
destination only as the shared Patroni-managed HA cluster. Keep the actual
address exclusively in access-controlled operational documentation.
- Line 266: load-test-plan.md のRPS記述を修正し、300人が5分間に1〜2リクエストを送る前提では平均約1〜2
req/sとして計算する。50〜100
req/sを維持する場合は、数秒以内の集中バーストなど具体的な時間窓と根拠を明示し、DBクエリ量およびVU計画の前提も整合させる。
- Line 327: 明確化する必要があるのは、S2の1
VU・60秒サイクルにおける操作確率モデルです。各エンドポイント操作を排他的な分岐として合計100%になるよう確率を定義するか、独立実行として1分あたりの期待操作回数を明記し、GET
/shift-cards、GET /shifts/tasks/...、レスキュー系、タスク系、POST /rescues、POST
/reviewsの実行条件と回数を再現可能な形に書き直してください。
- Around line 228-230: Clarify the load-test plan that the isolated postgres:18
setup provides only an “API implementation + isolated DB” baseline. Explicitly
state that its results must not be generalized to the production Patroni
cluster, whose hardware, configuration, and shared-resource contention are not
reproduced, while preserving the policy of excluding the shared production
database from load tests.
- Line 449: Update the RESCUE_GAS_URL HTTPS stub setup in the load-test plan to
install a dedicated trusted CA in the test container or configure the HTTP
client’s RootCAs for the self-signed certificate. Ensure POST /rescues succeeds
without TLS errors, and do not use InsecureSkipVerify.
- Line 138: load-test-plan.md
のエンドポイント内訳を表の分類と一致させてください。web_signin・web_signup・web_signoutをadmin(凍結)に含め、GET
/tasksをmobile側に数える前提で、adminを30ルート、デッドルートを27ルートとして本文の集計と説明を更新してください。
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9ae526f5-ac8c-4695-81c8-25e49f9bde74
📒 Files selected for processing (1)
docs/development/load-test-plan.md
- 本番DB内部IPアドレスの記載を削除し共有Patroniクラスタとのみ記載 - エンドポイント集計のadmin(凍結)/デッドルート数の入れ替わりを修正(30/27) - 隔離DBの試験結果を本番クラスタへ一般化しない旨を明記 - 300人×5分のRPS試算を修正し、クエリ増幅率とバースト幅の前提を明示 - S2シナリオの操作確率を独立試行として明確化(合計164%の曖昧さを解消) - RESCUE_GAS_URLスタブのTLS検証(信頼済みCA導入)の注意点を追加 - 作成日の表記を修正
GM・FinanSuはMySQL側(SeeFTはPostgres側)で接続プールは別物であり、 「接続上限の共有」という説明は不正確だった。実際のリスクはMySQL Server・ PostgreSQL・Patroni・etcdが同じ3台の物理ノード上で同居している点にあり、 既知のMySQLスワップ枯渇インシデントを実例として明記した。
インフラ班によるシナリオ①再試験の結果を8章として追記。シフトデータの 分散(1日50件→date_id1〜4に12件ずつ)、pgbouncer導入、N+1修正(PR #438) それぞれの効果を切り分けて記録。pgbouncerは500エラー・タイムアウトを 解消するが、N+1修正はその後も独立して+31%スループット・約4倍のレイ テンシ改善をもたらすことを実測。 また、本試験が2.4節の方針(隔離DBのみで試験)から外れ共有HAクラスタ上で 実施された点を確認事項として明記した。
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/development/load-test-plan.md`:
- Around line 541-553:
実測結果の表にp95およびp99の応答時間列を追加し、各負荷条件の実測値を記入してください。値を取得できない場合は、今回の結果を試験計画のpass/fail判定対象外と明記し、平均応答時間のみで判定しないようにしてください。
- Around line 541-553: Align the load-test description and table around the hey
command with the S1 burst model: either replace it with a k6
arrival-rate/stage/parallel scenario that sends 400 users within two seconds, or
explicitly label the current command as steady 200 req/s for 60 seconds. Also
document the hey timeout setting and the criteria used to calculate timeouts.
- Around line 559-560: 「プーラー導入だけで 500
エラー・タイムアウトが全て解消する」という断定を、再試験条件ではタイムアウトが発生しなかった旨の記述に変更する。初回試験と再試験ではシフト分布などの条件が異なるため、pgbouncer単独の因果効果を示さない表現にし、接続数制御がない点と非導入環境で再現しうる点は維持する。
- Around line 562-564: Update section 8.3 and the issue 3・4 execution
prerequisites to require a completed isolated database environment before
testing starts. Remove shared HA cluster use as a normal option; if an exception
is permitted, require explicit approval and resource monitoring.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: fe244907-4565-4007-8f19-142c3f05a1e4
📒 Files selected for processing (1)
docs/development/load-test-plan.md
| `hey -z 1m -c <VU> -q 0.5` で計測。DB プーラーは pgbouncer(`pool_mode=session`、`default_pool_size=50`。`pool_mode=transaction` では DB への通信が溢れたため session モードを採用)。Postgres 本体の `max_connections` は 100。 | ||
|
|
||
| | プーラー | N+1 | 負荷 | 要求レート | 実測 req/s | 500率 | タイムアウト率 | 平均応答 | | ||
| |---|---|---|---|---|---|---|---| | ||
| | なし | 未解決 | 400人/2秒 | 約200 req/s | 106.45 | 3.0% | 0% | 3.49秒 | | ||
| | なし | 未解決 | 200人/2秒 | 約100 req/s | 97.23 | 7.1% | 0% | 1.41秒 | | ||
| | なし | 未解決 | 100人/2秒 | 約50 req/s | 49.06 | 0.4% | 0% | 0.83秒 | | ||
| | あり | 未解決 | 400人/2秒 | 約200 req/s | 150.36 | 0% | 0% | 2.40秒 | | ||
| | あり | 未解決 | 200人/2秒 | 約100 req/s | 97.63 | 0% | 0% | 1.01秒 | | ||
| | あり | 未解決 | 100人/2秒 | 約50 req/s | 49.43 | 0% | 0% | 0.54秒 | | ||
| | あり | 解決済 | 400人/2秒 | 約200 req/s | **196.80** | **0%** | **0%** | **0.61秒** | | ||
| | あり | 解決済 | 200人/2秒 | 約100 req/s | 99.36 | 0% | 0% | 0.29秒 | | ||
| | あり | 解決済 | 100人/2秒 | 約50 req/s | 49.83 | 0% | 0% | 0.16秒 | |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win
p95/p99を実測結果に追加してください。
試験計画の判定基準がp95/p99である一方、この表は平均応答時間しか記録していません。現状ではpass/fail基準と比較できないため、p95/p99を追加するか、今回の結果は判定対象外と明記してください。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/development/load-test-plan.md` around lines 541 - 553,
実測結果の表にp95およびp99の応答時間列を追加し、各負荷条件の実測値を記入してください。値を取得できない場合は、今回の結果を試験計画のpass/fail判定対象外と明記し、平均応答時間のみで判定しないようにしてください。
🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "## files around load-test-plan"
git ls-files | grep -F 'docs/development/load-test-plan.md' || true
if [ -f docs/development/load-test-plan.md ]; then
echo "## file size"
wc -l docs/development/load-test-plan.md
echo "## relevant lines 520-570"
sed -n '520,575p' docs/development/load-test-plan.md | nl -ba -v520
echo "## search hey/k6/S1/load criteria"
rg -n "hey|k6|S1|バースト|負荷|タイムアウト|時間|秒|req/s|p9?5|p9?9|q =|q " docs/development/load-test-plan.md
fi
echo "## local hey docs if available"
command -v hey || true
if command -v hey >/dev/null 2>&1; then
hey -h 2>&1 | sed -n '1,120p'
fiRepository: NUTFes/SeeFT
Length of output: 335
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "## relevant lines 520-570"
sed -n '520,570p' docs/development/load-test-plan.md | awk '{printf "%5d %s\n", NR+519, $0}'
echo "## search hey/k6/S1/load criteria"
rg -n "hey|k6|S1|バースト|負荷|タイムアウト|時間|秒|req/s|p9?5|p9?9|q =|q |-c|-t|-z|-q" docs/development/load-test-plan.md
echo "## local hey docs if available"
command -v hey || true
if command -v hey >/dev/null 2>&1; then
hey -h 2>&1 | sed -n '1,120p'
fiRepository: NUTFes/SeeFT
Length of output: 14114
🌐 Web query:
rakyll hey documentation -c concurrent connections -q requests per second -z duration -t request timeout
💡 Result:
The hey tool (a load generator by rakyll) uses specific flags to control concurrent connections, request rate, duration, and timeouts [1][2]. Concurrent Connections The -c flag sets the number of workers (goroutines) to run concurrently [1][3]. Each worker processes requests in parallel [4]. The default is 50 [1][2]. Requests per Second (Rate Limiting) The -q flag sets a rate limit, defined as the maximum number of queries per second (QPS) per worker [1][3]. Note that this is a per-worker limit, not a global limit [3]. If you specify a duration with -z, the total throughput achieved will be approximately the -q value multiplied by the -c value [5]. Duration The -z flag sets the duration for which to send requests (e.g., -z 10s or -z 3m) [1][2]. When this flag is used, the -n flag (total number of requests) is ignored, and the tool will stop sending requests once the specified duration is reached [1][2]. Request Timeout The -t flag sets the timeout for each individual request in seconds [1][2]. The default value is 20 seconds, and setting it to 0 allows for an infinite timeout [1][6]. Summary of Flags: -c: Number of concurrent workers (default 50) [1][2]. -q: QPS limit per worker (default is no limit) [1][3]. -z: Duration of the test (e.g., -z 30s) [1][2]. -t: Timeout for each request in seconds (default 20) [1][6]. For example, to run a test with 10 concurrent workers at a rate of 5 QPS per worker for 30 seconds, you would use: hey -c 10 -q 5 -z 30s https://example.com [1]
Citations:
- 1: https://github.com/rakyll/hey
- 2: https://manpages.ubuntu.com/manpages/jammy/man1/hey.1.html
- 3: sjw1357/hey@36f181a
- 4: How is the concurrent requests sending? rakyll/hey#167
- 5: proposal: improve -q flag documentation rakyll/hey#158
- 6: context deadline exceeded (Client.Timeout exceeded while awaiting headers) rakyll/hey#277
S1 のバースト負荷モデルと hey を合わせてください。
hey -z 1m -c 400 -q 0.5 は1ワーカーあたり0.5 QPS、60秒間の定常負荷(約200 req/s)になるので、「400人が2秒以内に一斉アクセスするS1朝バースト」を再現しません。S1 のバースト再現が必要な場合は k6 のarrival rate/stage/parallel 制御を使うか、この行は「定常200 req/s・60秒」へ表記してください。-t / タイムアウト判定条件も併せ明示してください。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/development/load-test-plan.md` around lines 541 - 553, Align the
load-test description and table around the hey command with the S1 burst model:
either replace it with a k6 arrival-rate/stage/parallel scenario that sends 400
users within two seconds, or explicitly label the current command as steady 200
req/s for 60 seconds. Also document the hey timeout setting and the criteria
used to calculate timeouts.
| - **プーラー(pgbouncer)の導入だけで 500 エラー・タイムアウトが全て解消する。** これは 2.4 節が指摘した「API が接続プールの上限を設定していない(`SetMaxOpenConns` 等が存在しない)」問題に対し、DB 側手前にプーラーを挟むことで接続数を吸収した効果である。ただしこれはインフラ側(pgbouncer の設定)の対策であり、SeeFT のリポジトリ・API コード自体は接続数を制御していない状態のままである。プーラーが存在しない環境(`docker-compose.yml` を使うローカル開発環境や CI)ではこの問題は依然として再現しうる | ||
| - **N+1 修正(PR #438)は、プーラー導入後もなお独立して効果がある。** 400人負荷で 150.36 → 196.80 req/s(+約31%)、平均応答 2.40秒 → 0.61秒(約4倍)の改善が見られる。プーラーがボトルネックを吸収した後も、1リクエストあたりのクエリ数削減はスループット・レイテンシの両方に寄与することが実測で裏付けられた |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
pgbouncerの因果効果を過大に断定しないでください。
再試験ではpgbouncerなしでも全行のタイムアウト率が0%です。タイムアウト10.4%だった初回試験は、Line 536のとおりシフト分布も変更されています。したがって、「pgbouncerだけでタイムアウトが解消した」とは結論できず、「今回の再試験条件ではタイムアウトが発生しなかった」と記載してください。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/development/load-test-plan.md` around lines 559 - 560, 「プーラー導入だけで 500
エラー・タイムアウトが全て解消する」という断定を、再試験条件ではタイムアウトが発生しなかった旨の記述に変更する。初回試験と再試験ではシフト分布などの条件が異なるため、pgbouncer単独の因果効果を示さない表現にし、接続数制御がない点と非導入環境で再現しうる点は維持する。
| ### 8.3 試験環境についての確認事項 | ||
|
|
||
| 本節の試験は 2.4 節が明示した方針(「DB は共有クラスタに向けた試験を最初から実施しない」)から外れ、共有 HA クラスタ上の専用データベースに対して実施されている。結果として巻き込み事故は発生していないが、これは「今回はたまたま問題が起きなかった」以上の保証ではない。今後の試験(issue 3・4 の Track A/B 実行時など)でも同様に共有基盤を使うか、2.4 節の方針通り隔離 DB 環境を別途整備するかは、GM・FinanSu との巻き込みリスク(同一物理ノード上での CPU・メモリ・スワップ圧迫)を踏まえて改めて MT で確認する |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
共有HAクラスタ利用を後続試験の選択肢として残さないでください。
PRの方針は隔離DBのみの利用です。今回の逸脱を記録するだけでなく、issue 3・4を「隔離DB環境の整備完了」を開始条件にし、共有クラスタを使う場合は明示的な例外承認と資源監視を必須にしてください。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/development/load-test-plan.md` around lines 562 - 564, Update section
8.3 and the issue 3・4 execution prerequisites to require a completed isolated
database environment before testing starts. Remove shared HA cluster use as a
normal option; if an exception is permitted, require explicit approval and
resource monitoring.
対応Issue
resolve #434
概要
45th 本番前の API 負荷試験に向けた事前調査と試験計画(ドラフト・未実行)を
docs/development/load-test-plan.mdとして追加します。NUTFes Bingo 負荷試験報告書の方法論(原因切り分け、内部直結 vs 公開URL経由の比較、p95/p99 での pass/fail 基準)を踏襲しています。主な内容:
調査で判明した試験計画外のトピック(Access-Token ヘッダ欠落時の panic、
POST /request_shiftsのデッド化、mobile 静的配信のシングルスレッド問題など)は文書内のリスク・issue 提案節に記録しています。画面スクリーンショット等
テスト項目
ファイル:行番号引用が実コードと一致していること(スポットチェックで可)api/lib/router/router.goの全ルート +/swagger/*を網羅していること備考
試験の実行は本 PR のスコープ外です。マージ後、文書 7 章の提案に基づき後続 issue を起票してから着手します。
Summary by CodeRabbit