V0_53_TO_V1_5:>=0.53.0and<1.6.0V1_6_PLUS_V1_X:>=1.6.0and<2.0.0V2_0_PLUS:>=2.0.0
Always resolve exact version with k6 version before cloud guidance.
k6 cloud logink6 cloud run <script>k6 cloud run --local-execution <script>k6 cloud upload <script>
V0_53_TO_V1_5:
- Keep cloud guidance to login/run/local-execution.
- Do not assume stack/project routing by default.
V1_6_PLUS_V1_X:
- Allow
options.cloud.stackIDandK6_CLOUD_STACK_IDworkflows.
V2_0_PLUS:
- Require stack-aware cloud routing.
- Allow verified v2 options under
options.cloud.
Only use verified keys:
options.cloud.projectIDoptions.cloud.stackIDoptions.cloud.distributionoptions.cloud.deleteSensitiveDataoptions.cloud.staticIPsoptions.cloud.drop_metricsoptions.cloud.drop_tagsoptions.cloud.keep_tags
Use environment variables for auth/routing:
K6_CLOUD_TOKENK6_CLOUD_STACK_IDK6_CLOUD_PROJECT_ID
Before handing off to a runnable cloud path:
- Prefer
K6_CLOUD_TOKENfor non-interactive auth. - Otherwise require an interactive
k6 cloud loginstep before execution. - If auth readiness is unknown, keep the plan cloud-ready but mark execution as blocked until login or token setup is confirmed.
When options.cloud.distribution is present:
- Each entry must include
loadZoneandpercent. - Each
percentmust be an integer. - Percent total must equal
100. - If invalid, stop runnable handoff and request correction.
- Include explicit request timeout for executable HTTP examples (
timeout: '30s'baseline). - Use stricter values only when SLA requires them and document the rationale.
- Missing explicit timeout should be treated as a validation warning in
k6-validate, not an automatic blocker. - Plan and validation guidance must not contradict: if plan emits explicit timeout, validation should not warn on timeout absence.
Before generating executable HTTP scripts:
- Confirm endpoint path and primary method.
- For write methods (
POST,PUT,PATCH), confirm payload contract and expected status codes. - Confirm auth mechanism and required environment variables.
import http from 'k6/http';
import { check } from 'k6';
const BASE_URL = __ENV.BASE_URL;
if (!BASE_URL) {
throw new Error('BASE_URL environment variable is required');
}
export default function runHttpGetUsers() {
const response = http.get(`${BASE_URL}/users`, {
timeout: '30s',
tags: { name: 'get-users' },
});
check(response, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
}import http from 'k6/http';
const BASE_URL = __ENV.BASE_URL;
if (!BASE_URL) {
throw new Error('BASE_URL environment variable is required');
}
export default function runHttpBatchRequests() {
const responses = http.batch([
['GET', `${BASE_URL}/users`],
['GET', `${BASE_URL}/products`],
[
'POST',
`${BASE_URL}/orders`,
JSON.stringify({ item: 'test' }),
{
headers: { 'Content-Type': 'application/json' },
timeout: '30s',
tags: { name: 'create-order' },
},
],
]);
// Process responses[0], responses[1]
}import http from 'k6/http';
import { check } from 'k6';
const BASE_URL = __ENV.BASE_URL;
const API_USER = __ENV.API_USER;
const API_PASSWORD = __ENV.API_PASSWORD;
if (!BASE_URL || !API_USER || !API_PASSWORD) {
throw new Error('BASE_URL, API_USER, and API_PASSWORD environment variables are required');
}
export default function runHttpLoginFlow() {
const payload = JSON.stringify({
username: API_USER,
password: API_PASSWORD,
});
const params = {
headers: {
'Content-Type': 'application/json',
},
timeout: '30s',
tags: { name: 'login' },
};
const loginRes = http.post(`${BASE_URL}/login`, payload, params);
check(loginRes, {
'login status is 200': (r) => r.status === 200,
});
let token;
try {
token = loginRes.json('token');
if (!token) {
throw new Error('token field missing');
}
} catch (err) {
throw new Error(`Invalid login response JSON: ${err.message}`);
}
}import http from 'k6/http';
const BASE_URL = __ENV.BASE_URL;
const API_TOKEN = __ENV.API_TOKEN;
if (!BASE_URL || !API_TOKEN) {
throw new Error('BASE_URL and API_TOKEN environment variables are required');
}
export default function runHttpAuthenticatedPost() {
const payload = JSON.stringify({ item: 'test' });
const params = {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_TOKEN}`,
},
timeout: '30s',
tags: { name: 'create-order' },
};
http.post(`${BASE_URL}/orders`, payload, params);
}import grpc from 'k6/grpc';
import { check } from 'k6';
const GRPC_ADDR = __ENV.GRPC_ADDR;
if (!GRPC_ADDR) {
throw new Error('GRPC_ADDR environment variable is required');
}
const client = new grpc.Client();
client.load(['definitions'], 'service.proto');
export default function runGrpcUnaryCall() {
client.connect(GRPC_ADDR, {
plaintext: false,
});
const request = { name: 'test' };
const response = client.invoke('service.Method', request);
check(response, {
'status is OK': (r) => r && r.status === grpc.StatusOK,
});
client.close();
}const metadata = {
'authorization': `Bearer ${__ENV.GRPC_TOKEN}`,
};
const response = client.invoke('service.Method', request, { metadata });import { browser } from 'k6/browser';
const BASE_URL = __ENV.BASE_URL;
const UI_USER = __ENV.UI_USER;
const UI_PASSWORD = __ENV.UI_PASSWORD;
if (!BASE_URL || !UI_USER || !UI_PASSWORD) {
throw new Error('BASE_URL, UI_USER, and UI_PASSWORD environment variables are required');
}
export default async function runBrowserLoginJourney() {
const context = await browser.newContext();
const page = await context.newPage();
try {
await page.goto(BASE_URL);
await page.waitForSelector('input[name="login"]');
await page.fill('input[name="login"]', UI_USER);
await page.waitForSelector('input[name="password"]');
await page.fill('input[name="password"]', UI_PASSWORD);
await page.click('button[type="submit"]');
await page.waitForSelector('[data-testid="dashboard"]', { timeout: 5000 });
} finally {
await page.close();
await context.close();
}
}import { browser } from 'k6/browser';
import { check } from 'k6';
const BASE_URL = __ENV.BASE_URL;
if (!BASE_URL) {
throw new Error('BASE_URL environment variable is required');
}
export default async function runBrowserVitalsProbe() {
const context = await browser.newContext();
const page = await context.newPage();
try {
await page.goto(BASE_URL);
const fcp = await page.evaluate(() => {
const [entry] = performance.getEntriesByName('first-contentful-paint');
return entry ? entry.startTime : null;
});
check({ fcp }, {
'fcp captured': (m) => m.fcp !== null,
});
} finally {
await page.close();
await context.close();
}
}