Skip to content

test: add API stress tests#823

Open
G4614 wants to merge 1 commit into
mainfrom
stress/api-layer-k6
Open

test: add API stress tests#823
G4614 wants to merge 1 commit into
mainfrom
stress/api-layer-k6

Conversation

@G4614

@G4614 G4614 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Adds opt-in k6 stress tests for the deployed BoxLite REST API:

These tests are intentionally not part of the default test matrix because they target deployed APIs and can consume shared dev/runner capacity.

Validation

  • git diff --check
  • make -n test:stress:api-read-local
  • make -n test:stress:api-create-box-local
  • Installed and verified k6 v2.0.0
  • Ran local-network read canary against dev API:
    • 588 HTTP requests
    • 0.00% failures
    • p95 952ms
    • p99 1.37s

Notes

api-create-box.k6.js creates real boxes and deletes each successful create. It should be run deliberately with low rates first. A one-shot canary is available with:

BOXLITE_STRESS_ITERATIONS=1 make test:stress:api-create-box

Additional validation after opening the draft:

  • Ran one-shot box creation canary against dev API:
    • BOXLITE_STRESS_ITERATIONS=1 k6 run scripts/test/stress/api-create-box.k6.js
    • create returned 201
    • cleanup delete returned success
    • no stress-api-create-* boxes left behind

Read-only overload attempt from local network:

  • ramped read-only k6 profile to 50 iterations/sec (~200 HTTP req/sec requested)
  • k6 completed 7,868 HTTP requests with 0.00% request failures
  • latency degraded heavily: p95 15.92s, p99 27.96s, max 41s
  • k6 hit the 600 VU cap and dropped 937 iterations
  • CloudWatch during the run showed the API ECS service CPU peaking around 99.6% and ALB target response max around 34s
  • service remained stable on task definition Api:135

VM lifecycle stress update

Added api-vm-lifecycle.k6.js for real VM lifecycle stress. It uses a closed constant-vus model so each VU can hold at most one running VM at a time.

Safety guard:

  • BOXLITE_STRESS_VM_LIMIT <= BOXLITE_STRESS_RUNNER_CPUS * 8
  • BOXLITE_STRESS_VUS <= BOXLITE_STRESS_VM_LIMIT
  • the script throws at startup before sending requests if either guard is violated

Current dev runner i-0ee6bc569d5a1e9ef is c8i.2xlarge with 8 vCPU, so the hard ceiling is 64 simultaneous VMs. The local canary uses VM_LIMIT=2 / VUS=2, far below the ceiling.

Validation:

  • git diff --check
  • make -n test:stress:api-vm-lifecycle-local
  • guard canary: RUNNER_CPUS=1 VM_LIMIT=9 VUS=9 fails before sending requests
  • real VM canary: VM_LIMIT=2 VUS=2 DURATION=25s HOLD_SECONDS=10, 4 create/run/delete iterations, 0 failures, no stress-api-vm-* leftovers

Real VM stress run, 4 concurrent VMs

Ran a real VM lifecycle stress against dev with BOXLITE_STRESS_RUNNER_CPUS=8, BOXLITE_STRESS_VM_LIMIT=4, BOXLITE_STRESS_VUS=4, BOXLITE_STRESS_DURATION=90s, BOXLITE_STRESS_HOLD_SECONDS=20.

Safety: max simultaneous VMs was 4, below the current dev runner hard ceiling of 8 vCPU * 8 = 64.

Result:

  • 19 complete create/run/delete iterations
  • 38 HTTP requests
  • 0 failed checks, 76/76 checks passed
  • 0 interrupted iterations
  • http_req_failed: 0.00%
  • http_req_duration: avg 850.73ms, p90 1.78s, p95 1.86s, p99 2.49s, max 2.85s
  • iteration_duration: avg 22.37s, p90 25.46s, p95 25.71s, p99 26.59s, max 26.81s
  • leftover check: stress-api-vm-* returned []

Summary by CodeRabbit

  • New Features
    • Added new k6 stress-test scenarios for deployed REST APIs: API read checks, box creation, and VM lifecycle management (with local-profile variants).
    • Introduced new make targets to run these stress tests against deployed and local environments.
  • Documentation
    • Added an opt-in stress testing guide covering each scenario’s purpose, configuration options, and monitoring guidance.
  • Chores
    • Extended make help to list the new stress-test targets.
    • Added Biome configuration to exclude stress test .k6.js scripts from formatting/linting.

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 677da49e-ab59-435e-9e35-acbb9c23c376

📥 Commits

Reviewing files that changed from the base of the PR and between 540fb01 and dbdc626.

📒 Files selected for processing (7)
  • biome.json
  • make/help.mk
  • make/test.mk
  • scripts/test/stress/README.md
  • scripts/test/stress/api-create-box.k6.js
  • scripts/test/stress/api-read.k6.js
  • scripts/test/stress/api-vm-lifecycle.k6.js
✅ Files skipped from review due to trivial changes (2)
  • make/help.mk
  • scripts/test/stress/README.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • make/test.mk
  • scripts/test/stress/api-create-box.k6.js
  • scripts/test/stress/api-read.k6.js
  • scripts/test/stress/api-vm-lifecycle.k6.js

📝 Walkthrough

Walkthrough

Three k6 stress test scripts are added for Boxlite's REST API: a read-only scenario, a box creation/deletion scenario, and a VM lifecycle (create→running→delete) scenario. Six corresponding make targets (deployed and local variants) are registered in test.mk and help.mk, and a README.md documents all three. A biome.json configuration file excludes k6 scripts from formatting.

Changes

k6 Stress Test Scripts, Make Targets, and Documentation

Layer / File(s) Summary
api-read k6 script
scripts/test/stress/api-read.k6.js
Env-driven config, ramping-arrival-rate scenario with p95/p99 thresholds, authParams/checkStatus helpers, setup() validation, and a default VU function issuing authenticated GET/HEAD requests against health, config, user, and boxes endpoints.
api-create-box k6 script
scripts/test/stress/api-create-box.k6.js
Env config with conditional scenario (shared-iterations vs ramping-arrival-rate), auth/naming/JSON helpers, setup() validation, and a default VU function that POSTs to create a box, checks 201/box_id, optionally DELETEs on cleanup, then sleeps.
api-vm-lifecycle k6 script
scripts/test/stress/api-vm-lifecycle.k6.js
Env parsing with hard-limit guardrails (VM_LIMIT ≤ runner CPUs × 8, VUS ≤ VM_LIMIT), constant-VU scenario options, auth/naming helpers, waitForRunning() polling loop, setup() validation, and a default VU function that creates a VM box, waits for running, holds, then deletes in a finally block.
Make targets, help entries, and README
make/test.mk, make/help.mk, scripts/test/stress/README.md
Six make targets (deployed and -local variants) with defaultable BOXLITE_STRESS_* env vars are added to test.mk; corresponding help entries added to help.mk; README documents all three scenarios with required env vars, override parameters, and safety warnings.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Hop, hop, the VUs race,
Boxes born and deleted with grace,
k6 scripts now stress the REST,
Thresholds set to pass the test,
Local and deployed, two paths to run —
This bunny's stress suite has just begun! 🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'test: add API stress tests' is directly related to the main changes, which introduce three new k6 stress test scripts (api-read.k6.js, api-create-box.k6.js, api-vm-lifecycle.k6.js) for deployed REST APIs.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch stress/api-layer-k6

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cla-assistant

cla-assistant Bot commented Jun 17, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@G4614 G4614 force-pushed the stress/api-layer-k6 branch 3 times, most recently from 2df7c4f to a73b802 Compare June 17, 2026 12:07
@G4614 G4614 marked this pull request as ready for review June 17, 2026 12:13
@G4614 G4614 requested a review from a team as a code owner June 17, 2026 12:13
@G4614 G4614 enabled auto-merge June 17, 2026 12:13

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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 `@scripts/test/stress/api-create-box.k6.js`:
- Around line 92-103: The cleanup operation is currently gated on the `created`
variable which requires both a 201 status AND a valid box_id in the response.
This means if the create request returns 201 but the response structure is
malformed or missing box_id, the cleanup will be skipped and boxes will be left
behind. Modify the cleanup condition to gate it on the HTTP create success
(checking create.status === 201 directly) rather than the `created` check
result, while still using the fallback logic for boxId extraction. This ensures
cleanup runs whenever the create request succeeds at the HTTP level, regardless
of response validation results.

In `@scripts/test/stress/api-vm-lifecycle.k6.js`:
- Around line 95-109: The code currently checks the box status only once on the
create response and returns early if it is not already running, which prevents
the test from waiting for the running state to be reached. After the initial
create request and the check block that validates the 201 response and box_id
presence, add a polling loop that repeatedly fetches the box status using an
HTTP GET request to the box endpoint and checks if the status equals running,
continuing to poll with a small sleep interval until the running state is
achieved before proceeding to the sleep(HOLD_SECONDS) call. This ensures the
actual "create → wait for running → hold → delete" lifecycle flow is executed as
intended.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 54846999-8557-4108-bc09-6466bd97a93d

📥 Commits

Reviewing files that changed from the base of the PR and between 9e153f8 and a73b802.

📒 Files selected for processing (6)
  • make/help.mk
  • make/test.mk
  • scripts/test/stress/README.md
  • scripts/test/stress/api-create-box.k6.js
  • scripts/test/stress/api-read.k6.js
  • scripts/test/stress/api-vm-lifecycle.k6.js

Comment thread scripts/test/stress/api-create-box.k6.js Outdated
Comment thread scripts/test/stress/api-vm-lifecycle.k6.js
@G4614

G4614 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@G4614 G4614 force-pushed the stress/api-layer-k6 branch from a73b802 to 6324d81 Compare June 17, 2026 12:34

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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 `@scripts/test/stress/api-vm-lifecycle.k6.js`:
- Around line 74-90: The polling loop in the VM box status check treats a 404
response as immediately terminal by returning false, which fails valid create
flows under eventual consistency where the box may not be queryable immediately
after creation. Remove the early return statement when info.status === 404 (the
check block that returns false on line 85) and instead allow the polling loop to
continue iterating until either the resource becomes available with status 200
and 'running' state, or the deadline expires. This way, transient 404s during
the eventual consistency window will be retried rather than causing premature
failure.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b88c35bf-fe74-4a7b-95e5-d6f45dcec290

📥 Commits

Reviewing files that changed from the base of the PR and between a73b802 and 6324d81.

📒 Files selected for processing (6)
  • make/help.mk
  • make/test.mk
  • scripts/test/stress/README.md
  • scripts/test/stress/api-create-box.k6.js
  • scripts/test/stress/api-read.k6.js
  • scripts/test/stress/api-vm-lifecycle.k6.js
✅ Files skipped from review due to trivial changes (2)
  • make/help.mk
  • scripts/test/stress/README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • make/test.mk

Comment thread scripts/test/stress/api-vm-lifecycle.k6.js
@G4614 G4614 force-pushed the stress/api-layer-k6 branch from 6324d81 to 540fb01 Compare June 17, 2026 12:44

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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 `@scripts/test/stress/api-create-box.k6.js`:
- Around line 1-2: Biome cannot parse the ES6 import/export statements in the k6
files because it lacks ES module configuration. Update the biome.json
configuration file to add a sourceType: "module" override specifically for the
scripts/test/stress/**/*.k6.js pattern, or alternatively exclude the
scripts/test/stress directory from the linting scope in the biome.json
configuration to prevent Biome from processing these k6 test files that use ES
module syntax.

In `@scripts/test/stress/api-vm-lifecycle.k6.js`:
- Around line 11-18: Add explicit validation after parsing the environment
variables to ensure that VM_LIMIT, VUS, WAIT_RUNNING_MS, and POLL_SECONDS are
positive finite numbers. After each Number() conversion for these variables, add
checks to validate that the parsed value is greater than 0 and is a finite
number (not NaN, Infinity, or negative), and throw or log an appropriate error
if validation fails. The same validation pattern should also be applied to the
variables mentioned in the "Also applies to" note at line 27-29.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2cc14ecf-f21b-4b4b-94df-c8439bb1a69b

📥 Commits

Reviewing files that changed from the base of the PR and between 6324d81 and 540fb01.

📒 Files selected for processing (6)
  • make/help.mk
  • make/test.mk
  • scripts/test/stress/README.md
  • scripts/test/stress/api-create-box.k6.js
  • scripts/test/stress/api-read.k6.js
  • scripts/test/stress/api-vm-lifecycle.k6.js
✅ Files skipped from review due to trivial changes (1)
  • scripts/test/stress/README.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • make/help.mk
  • make/test.mk

Comment thread scripts/test/stress/api-create-box.k6.js
Comment thread scripts/test/stress/api-vm-lifecycle.k6.js
@G4614 G4614 force-pushed the stress/api-layer-k6 branch from 540fb01 to dbdc626 Compare June 17, 2026 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant