Generated banner for K6 Test Maintenance
Generated logo for K6 Test Maintenance

K6 Test Maintenance

Grafana LabsOfficialPublished by Grafana Labs

  • Skill
  • Workflow
  • Software development
  • Apache-2.0
  • No issues found

From the author

Maintain and improve existing k6 test scripts. Covers threshold tightening based on trend data, version migration between k6 releases, auto-fixing tests when the underlying service changes, refactoring for cleanliness, and auditing scripts against current best practices from docs. Use when the user asks to fix a failing k6 test, tighten thresholds, migrate a script to a new k6 version, refactor a test, update a script after a service change, or improve a script with best practices. Trigger on phrases like "fix my k6 test", "tighten my thresholds", "migrate to k6 v2", "update my test script", "refactor this k6 test", "my test is failing after a deploy", "apply best practices to my script", "modernize my k6 test", or "the service changed and my test broke". Also trigger when another skill (k6-trend-analysis or k6-cloud-investigate-test) hands off with a recommendation to edit a script. Maintains existing scripts; to author a new test use the k6 skill, or k6-browser-test for a browser test.
— the description by Grafana Labs

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

The k6-test-maintenance skill provides a structured, safety-first approach to updating existing k6 performance tests. It covers five core maintenance tasks: threshold tightening, version migration, service change adaptation, code refactoring, and best-practices auditing. The skill enforces a strict behavior-aware change control process, distinguishing between syntactic changes (which can be applied automatically) and behavioral changes (which require user review and confirmation). It integrates with k6-manage and Grafana Cloud APIs to ensure that all modifications are validated through parse-checks and cloud-based smoke tests before being finalized.

What it does

  • Tightens threshold values based on historical trend data and metric observations.
  • Migrates scripts to newer k6 versions by identifying deprecated APIs and patterns.
  • Adapts existing test scripts to accommodate changes in the underlying service.
  • Refactors test code for improved cleanliness and adherence to current best practices.
  • Audits scripts against official k6 documentation to ensure optimal performance and reliability.
  • Validates all changes using a multi-stage process including parse-checks and cloud smoke runs.

When to use it

  • When a test is failing after a service deployment or infrastructure change.
  • When you need to update thresholds to reflect current performance trends.
  • When migrating legacy scripts to a newer k6 release.
  • When you want to refactor or modernize your existing test codebase.
  • When you need to ensure your scripts align with current k6 best practices.

Advantages

  • Reduces risk by classifying changes as syntactic or behavioral before application.
  • Prevents breaking CI gates or SLOs through rigorous verification recipes.
  • Grounds all recommendations in official k6 documentation and API references.
  • Provides a safe, standardized workflow for cloud-hosted script management.
  • Minimizes manual effort by automating syntactic refactoring and validation.

Usage examples

“My k6 test is failing after the latest service deployment, can you fix it?”
The agent will analyze the service changes, identify the impact on the test script, propose necessary adjustments, and guide you through the verification process.
“Tighten my p95 thresholds based on the last 30 days of data.”
The agent will query historical metrics, calculate appropriate new thresholds, present a pass/fail impact table, and apply the changes upon your approval.
“Migrate this script to k6 v2.”
The agent will identify deprecated APIs, propose the required syntax updates, and perform a cloud smoke test to ensure the migrated script functions correctly.
“Refactor my k6 test to follow best practices.”
The agent will audit the script for common issues, suggest cleaner patterns, and provide a diff for any behavioral changes before applying them.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/grafana/k6-test-maintenance/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip k6-test-maintenance.zip -d .agents/skills

Documentation by Grafana Labs

k6 Test Maintenance

Maintain, fix, and improve existing k6 test scripts. Five maintenance tasks, each with a step-by-step procedure in references/workflows.md:

  1. Threshold tightening -- adjust threshold values based on observed metrics

  2. Version migration -- update scripts for new k6 releases

  3. Service change adaptation -- fix tests when the underlying service changes

  4. Refactoring -- clean up and modernize test code

  5. Best practices audit -- check scripts against current k6 best practices

Core principle: behavior-aware change control

Classify every proposed change by whether it alters the test's runtime behavior:

  • Syntactic (behavior unchanged): the k6 runtime produces identical metrics, pass/fail results, and endpoints. Examples: rename a variable, let → const, remove unused imports, update comments, reformat. Apply directly.

  • Behavioral (behavior differs): anything affecting metrics, pass/fail, timing, request targets, or load shape. Examples: threshold value changes, adding sleep(), endpoint URL updates, check rewrites, scenario changes, new thresholds. Always present as a diff with rationale and require confirmation.

The threshold for "behavioral" is deliberately low. If in doubt, treat it as behavioral and ask -- a trivial-looking threshold change can cascade to CI gates, SLO calculations, and alerting.

Dependencies

  • k6-manage -- fetch and edit GCk6-hosted scripts safely (§5: GET, backup, edit, validate, PUT, verify by sha256). Read it before touching any cloud-hosted script.

  • gcx -- sole tool for Grafana Cloud API access.

  • mcp-k6 tools -- validate_script and get_documentation. Check availability first; fall back to k6 x docs if absent.

  • k6 x docs CLI -- documentation lookup when mcp-k6 isn't configured.

  • k6 CLI -- local validation (k6 inspect, k6 run).

Validation loop (every edit)

Every workflow produces a modified script. Never present or PUT an unvalidated script -- run this loop, fixing and re-running until it passes:

  1. Parse-check: k6 inspect <script> -- catches syntax errors, invalid options, broken imports. Works on all types including browser tests (no browser needed). If mcp-k6 is available, also run validate_script.

  2. Local smoke (non-browser, service reachable): k6 run --vus 1 --iterations 1 <script>.

  3. Classify the change (below) and verify per the matrix -- recipes in references/verification.md.

  4. Cloud-hosted scripts: apply via the k6-manage §5 safe-edit recipe (GET → backup → edit → validate → PUT as application/octet-stream → sha256-verify).

Change classification
  • Class A -- declarative-config only. The diff is confined to options.thresholds or similar declarative fields that don't alter what the k6 runtime executes; the bytes inside default function, imported modules, and check predicates are byte-identical. Example: p(95)<500 → p(95)<420.

  • Class B -- runtime logic changes. Any change to default function, imports, helper modules, request URLs, check predicates, or to scenarios.*.vus/iterations/duration/executor (which alter load shape and metric distributions). Example: changing a URL, adding a check, rewriting auth, switching executors.

When in doubt, treat as Class B.

Verification matrix
ClassTest durationVerification
Aanysha256 + k6 inspect + historical pass/fail prediction. No cloud run needed.
Bshort (< 5 min)sha256 + k6 inspect + full cloud run (k6-manage §11).
Blong (≥ 5 min)sha256 + k6 inspect + local 1-iteration smoke + k6 cloud run of a local copy with --vus 1 --iterations 1. PUT to the saved test only after the cloud smoke passes.

Verification depth depends on the change class, not the test's duration -- most edits don't need a full run, and production tests may run for hours. Per-class recipes (Class A prediction table, Class B short/long, edge cases like scenario changes and loosening) are in references/verification.md.

Documentation lookup

Before proposing any change that touches k6 APIs, imports, or patterns, confirm it against current docs and cite the source in your report -- this grounds recommendations in the real API, not stale model knowledge. Look up in order:

  1. mcp-k6 (preferred): get_documentation("best_practices"), get_documentation("javascript-api/k6-browser"), validate_script(...).

  2. k6 x docs CLI (always available):

    k6 x docs using-k6 thresholds
    k6 x docs javascript-api k6-http
    k6 x docs search "websocket migration"

    2-call strategy: try the direct path first; if it returns a topic list, pick the subtopic and call again. Full parent paths required (using-k6 thresholds, not thresholds). k6 x docs serves docs for the installed k6 version -- it may lag the target version when migrating.

  3. Web fetch (last resort): https://grafana.com/docs/k6/latest/.

Async check pattern

A common browser-test bug: using check() from k6 with async predicates. The built-in check() does not await Promises, so check(page, { 'title': p => p.locator('h1').textContent() === 'Foo' }) silently passes because the Promise object is truthy. Two valid fixes:

  • Async-aware check from jslib: import { check } from 'https://jslib.k6.io/k6-utils/1.5.0/index.js' -- then predicates can be async and await inside them works.

  • Resolve the value before the check: const text = await page.locator('h1').textContent(); check(text, { ... }) -- keeps the standard sync check from k6.

When you hit this during any workflow (migration, refactor, audit), flag it as a behavioral bug and propose one of these fixes.

Script sources

  • GCk6-hosted -- fetched and pushed via k6-manage §5 (GET → backup → edit → validate → PUT → verify sha256).

  • Local on disk -- read and edit directly. Validate before presenting.

Determine the source before starting: a GCk6 test URL or ID is cloud-hosted; a file path is local.

Authoring a new test, not maintaining one? This skill improves scripts that already exist. To write a new browser test from a plain-language user journey (selectors discovered by exploring the live site), use the k6-browser-test skill; for other new k6 scripts, use the k6 skill.

Workflows

Full procedures are in references/workflows.md:

  • Threshold tightening -- propose values with observed-metric justification, diff, apply, Class A verify.

  • Version migration -- find deprecated/renamed APIs, classify syntactic vs behavioral, apply, Class B verify.

  • Service change adaptation -- map each service change to a script change, propose fixes, Class B verify.

  • Refactoring -- find issues, auto-apply syntactic, propose behavioral, Class B verify after confirmation.

  • Best practices audit -- doc-driven audit across thresholds, load design, resource management, code quality, and browser specifics.

All five follow behavior-aware change control: auto-apply syntactic changes, present behavioral ones as diffs for confirmation.

Gotchas

IssueDetail
Cloud script formatGCk6 scripts can be single files or tar archives. Detect with file(1) before editing (see k6-manage §5).
Zero-observation thresholdsA threshold on a metric with no observations passes by default. When adding new thresholds, ensure the metric is actually emitted by the test.
abortOnFail cascadesIf a threshold has abortOnFail: true, tightening it means runs abort earlier. Warn the user.
Browser script validationBrowser scripts can't be validated with k6 run --iterations 1 without a browser. Use k6 inspect for parse-only validation, or validate_script via mcp-k6.
k6 x docs version alignmentk6 x docs serves docs for the installed k6 version; when migrating to a newer version, local docs may not reflect the target API. Note this in migration lookups.
Script drift after editAfter pushing a cloud-hosted script, the next run uses the new version, but historical runs keep their bundled snapshot. To investigate a past failure, compare the run-bundled script (read-only), not the current one.

References

Files

references/workflows.md

Maintenance workflows

Step-by-step procedures for the five maintenance tasks. All apply the behaviour-aware change control, mandatory validation, and post-edit verification defined in SKILL.md; verification recipes are in verification.md.

Contents

  • Threshold tightening

  • Version migration

  • Service change adaptation

  • Refactoring

  • Best practices audit

Threshold tightening

Typically triggered by k6-trend-analysis recommendations or user request.

Step 1: Understand the current state

Gather the inputs:

  • The current script (cloud or local)

  • The current threshold definitions

  • Trend data or metric observations that motivate the change (from k6-trend-analysis output, user-provided data, or fresh metric queries via k6-manage)

Step 2: Propose new threshold values

For each threshold being tightened:

  • State the current value and the proposed value

  • Show the observed metric that justifies the change (e.g., "P95 is currently 380ms, proposing p(95)<450 to give 18% headroom")

  • Note any downstream impact: does this threshold have abortOnFail? Is it referenced in CI gates or SLO definitions?

Step 3: Present the diff

Show a clear before/after diff of the thresholds block. This is a behavioral change -- always wait for user confirmation.

Step 4: Apply and verify

After confirmation:

  1. Apply the change to the script

  2. Validate: k6 inspect (parse check) or validate_script (mcp-k6)

  3. For cloud-hosted scripts, follow k6-manage Section 5 safe-edit recipe (backup → PUT → sha256-verify)

  4. Verify per the verification matrix in SKILL.md. Threshold changes are Class A -- use the historical pass/fail prediction recipe (verification.md § Class A). For loosening, the prediction table also surfaces which past failing runs are being "hidden" by the change, which the user should see before the PUT.

  5. Confirm the change was applied.

Version migration

Triggered when the user wants to update a script for a new k6 release, or when deprecated APIs are detected.

Step 1: Identify what needs migration

Read the script and look for:

  • Deprecated imports (e.g., k6/ws → k6/experimental/websockets)

  • Removed or renamed APIs

  • Changed option formats (e.g., ext.loadimpact → cloud)

  • Patterns that have newer alternatives

Use documentation to confirm migrations:

  1. Check mcp-k6 get_documentation for migration guides (preferred)

  2. Fall back to k6 x docs using-k6 javascript-api for API reference

  3. Last resort: web fetch from https://grafana.com/docs/k6/latest/

Step 2: Classify each change

For each required migration:

  • Is the API identical after the import swap? (e.g., same function signatures, same behavior) → syntactic change, can auto-apply

  • Does the API differ? (e.g., different method names, new patterns required) → behavioral change, must propose and confirm

Step 3: Apply syntactic changes

Auto-apply all purely syntactic migrations (import path swaps where the API surface is identical). Show a summary of what was changed.

Step 4: Propose behavioral changes

For each migration that changes behavior:

  • Show the old pattern and the new pattern side by side

  • Explain what differs in behavior

  • Cite the documentation source

Wait for user confirmation before applying each one.

Step 5: Validate and verify

After all changes are applied:

  1. Run k6 inspect or validate_script to confirm the script parses

  2. Verify per the verification matrix in SKILL.md. Migration edits are Class B by definition (imports and APIs changed), so choose the short-vs-long-test path based on the saved test's expected duration. Don't skip the cloud smoke for long tests just because the change "looks like a rename" -- migration bugs often hide in cloud-only behaviour (load-zone connectivity, env-var resolution).

  3. Present the verification result.

Service change adaptation

Triggered when a test starts failing because the underlying service changed (new endpoints, different response schema, changed auth), or when k6-cloud-investigate-test hands off after identifying a service-side cause.

Step 1: Understand what changed

Gather evidence of what changed on the service side:

  • If coming from k6-cloud-investigate-test: read the investigation report for the specific failure details (error messages, status codes, response bodies)

  • If the user describes the change: confirm the specifics (what endpoint changed, what the new behavior is)

  • If neither: fetch the most recent failing run's logs via k6-manage Section 4 and compare with the last passing run to identify the delta

Step 2: Categorize the changes needed

Map each service change to a script change:

Service changeScript impactComplexity
Endpoint URL changedUpdate URL stringSimple if new URL known
Response field renamedUpdate check assertionsModerate
New required header/paramAdd to request configModerate
Auth mechanism changedRewrite auth flowComplex
Response schema restructuredRewrite extraction + checksComplex
Endpoint removed/replacedRewrite entire requestComplex
Step 3: Propose fixes

For each change:

  • Show the current failing code and the proposed fix

  • Explain the rationale (what changed on the service side)

  • All of these are behavioral changes -- present as a diff with rationale

For complex changes where the "right" fix depends on user intent:

  • Present multiple options if applicable

  • Flag what you're uncertain about

  • Ask the user to clarify before proceeding

Step 4: Validate and verify

After confirmation and applying changes:

  1. Validate with k6 inspect or validate_script

  2. Verify per the verification matrix in SKILL.md. Service-change fixes are Class B (request URLs, check predicates, or auth flow changed). The cloud smoke is especially important here -- a fix that works locally against your laptop's network may still hit the wrong host or fail auth from cloud load zones.

  3. Confirm the previously-failing checks now pass against the new service shape.

Refactoring

Triggered by user request to clean up or modernize a test script.

Step 1: Read and analyze the script

Look up best practices in the docs before analyzing -- don't rely on model knowledge alone. Run k6 x docs using-k6-browser/recommended-practices for browser tests, k6 x docs using-k6 thresholds for threshold patterns, etc.

Identify issues:

  • Dead code (unused variables, unreachable branches)

  • Duplicated logic that could be extracted to helper functions

  • Overly complex structure that could be simplified

  • Inconsistent naming or patterns

  • Missing error handling (e.g., no try/finally for browser tests)

  • Deprecated patterns (e.g., waitForNavigation, networkidle, type() instead of fill())

  • Async bugs (e.g., async methods inside sync check() predicates)

  • Missing thresholds or performance guards

Be thorough. The user asked for a refactor -- find everything, even if some findings are behavioral. The classification framework exists to handle this: you'll auto-apply the syntactic ones and propose the behavioral ones. Don't self-censor by leaving out findings you're unsure about -- classify them and let the user decide.

Step 2: Classify each change

Apply the behavior-aware rule:

  • Syntactic (auto-apply): variable renames, let → const, remove unused imports, reformat, add/update comments, extract pure helper functions that don't change call semantics

  • Behavioral (propose + confirm): adding try/finally error handling, restructuring scenarios, changing group boundaries, extracting logic that changes execution order

Step 3: Apply and propose
  1. Auto-apply all syntactic changes to the output script

  2. Do NOT apply behavioral changes to the output script -- describe them in the report as proposals with diffs and rationale

  3. The output script should reflect ONLY syntactic fixes so the user can see what was safely changed vs what needs their approval

  4. Run k6 inspect on the output script to validate it

Step 4: Apply behavioral changes after confirmation

Once the user confirms, apply behavioral changes, re-validate, then verify per the verification matrix in SKILL.md. A refactor that "shouldn't change behaviour" still needs Class B verification because the classification is about the diff, not the intent -- if any runtime byte changed, treat it as Class B.

Best practices audit

Triggered by user request, or as a secondary check during any other maintenance workflow. Uses documentation to identify improvements.

Step 1: Establish the documentation source and look up best practices

This step is not optional. Look up documentation before auditing -- do not rely solely on model knowledge.

Try in order:

  1. mcp-k6: call get_documentation for best practices

  2. k6 x docs: run k6 x docs using-k6 for general guidance, then topic-specific lookups as needed (e.g., k6 x docs using-k6-browser/recommended-practices for browser tests)

  3. Web fetch: https://grafana.com/docs/k6/latest/ as last resort

For browser tests specifically, look up:

  • k6 x docs using-k6-browser/recommended-practices

  • k6 x docs javascript-api k6-browser page

  • k6 x docs javascript-api k6-browser locator

Step 2: Audit the script

Check against these categories:

Thresholds and assertions:

  • Are thresholds defined? (At minimum: http_req_duration and http_req_failed for HTTP tests)

  • Are check() or expect() assertions on every response?

  • Are thresholds realistic based on the test type?

Load design:

  • Is sleep() present in load tests? (Required for realistic think time)

  • Are scenarios using appropriate executors for the test type?

  • Is the VU/iteration count reasonable?

Resource management:

  • Browser tests: try/finally with page.close() in finally?

  • gRPC tests: client.close() after each iteration?

  • File handles and connections properly closed?

Code quality:

  • const instead of let/var at module level?

  • No deprecated imports?

  • No hardcoded secrets? (Should use __ENV or environment variables)

  • SharedArray for test data files?

Browser-specific (if script imports k6/browser):

  • Using getBy* APIs (getByRole, getByLabel, getByText, getByTestId) instead of generic page.locator() where possible?

  • Not calling waitFor() before interactions (built-in actionability)?

  • Not using waitForLoadState() after navigation?

  • Using page.waitForTimeout() instead of sleep() in browser context?

Step 3: Present findings

Produce an audit report:

## Best Practices Audit: {script_name}

### Passed
- [x] Thresholds defined
- [x] Checks on responses
- [x] sleep() between iterations

### Needs attention (behavioral changes -- requires confirmation)
- [ ] **Add try/finally for browser cleanup**: page.close() is not in a
      finally block. If a test step throws, the browser page leaks.
      [Doc: k6 x docs javascript-api k6-browser page]
- [ ] **Use getByRole instead of locator**: 3 instances of
      page.locator('input[name="..."]') could use getByRole('textbox').
      [Doc: k6 x docs javascript-api k6-browser locator]

### Auto-applied (syntactic -- no behavior change)
- [x] Changed 2 `let` declarations to `const` (lines 12, 45)
- [x] Removed unused import `encoding` (line 3)
Step 4: Produce the output script

Apply syntactic changes to a copy of the script and save it. Behavioral changes should be described in the report but NOT applied to the output script -- they are proposals awaiting confirmation. The output script should contain only the syntactic (auto-applied) fixes so the user can see the safe changes separately from the proposed behavioral ones.

Run k6 inspect on the output script to validate it parses correctly.

Step 5: Apply behavioral changes after confirmation

Once the user confirms specific behavioral changes, apply them to the script, re-validate, and verify per the verification matrix in SKILL.md. Audit-driven changes are Class B by default.

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs network access

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
Grafana Labs
Publisher
Grafana Labs (Official)
Source
grafana/skills · skills/grafana-k6/k6-test-maintenance · commit 8fb72a5
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Grafana Labs or Grafana Labs.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download k6-test-maintenance.zip