Scaling load tests from a local machine to distributed execution on k6 Cloud with k6 login cloud and k6 cloud, understanding load zones and how k6 Cloud orchestrates up to hundreds of thousands of virtual users, plus exploring the self-managed alternative using xk6 and the Kubernetes operator.

Episode 16 turned k6 into a pipeline guard — every merge request and release is now automatically performance-tested. But there's a limit you haven't touched yet: how much load can one machine generate? For smoke tests and small load tests, the answer is enough. For simulating nationwide traffic on promo day, a single k6 binary on a runner will never be enough.
Episode 17 opens the door to a larger scale: distributed load testing and cloud execution. We'll get to know k6 Cloud, how load zones work, how thousands of instances are orchestrated to generate hundreds of thousands of virtual users, plus the self-managed alternative using xk6 and the Kubernetes operator.
Before talking about the cloud, let's be honest about local capacity. A single k6 process on a single machine is an efficient machine — for simple scripts, tens of thousands of VUs are still reasonable on decent hardware. But there are four constraints that can't be broken just by adding VUs:
Distribution solves all these constraints at once by splitting the VUs across many machines.
k6 Cloud is a managed service from Grafana Cloud that runs k6 in a distributed fashion. The good news: you don't need to rewrite your scripts. The same script you run with k6 run script.js simply gets redirected to the cloud — all the VU, scenarios, checks, and thresholds concepts still apply.
Two commands switch you to cloud mode:
k6 login cloud --token <k6-cloud-token>
k6 cloud script.jsk6 login cloud --token stores your credential on your machine (the token can also be provided via the K6_CLOUD_TOKEN environment variable, suitable for CI). Next, k6 cloud script.js uploads the script along with its dependencies to k6 Cloud, starts the test, and prints a results page URL that shows the metrics in real time. All the orchestration — splitting VUs across instances, running, aggregating metrics — is handled by the cloud.
A load zone is the geographic location where k6 workers run. By directing parts of traffic from several regions, you simulate real users: 50% from Jakarta is not the same as 50% from Frankfurt in terms of latency and routing. The configuration is done via options.cloud inside the script:
export const options = {
scenarios: {
flash_sale: {
executor: 'ramping-vus',
startVUs: 0,
stages: [
{ duration: '5m', target: 5000 },
{ duration: '10m', target: 5000 },
{ duration: '5m', target: 0 },
],
},
},
cloud: {
name: 'Flash Sale - 10K VU',
projectID: 123456,
loadZones: [
{ name: 'ap-southeast-1', percent: 60 },
{ name: 'us-east-1', percent: 40 },
],
},
};With loadZones, 60% of the VUs are generated from ap-southeast-1 and 40% from us-east-1. Notice that the scenario is still defined as usual — the cloud only determines where the VUs come from.
How does k6 Cloud generate hundreds of thousands of VUs? The answer is orchestration: a control plane splits the total VUs into many chunks, assigns each chunk to a cloud worker instance, runs all the workers in parallel, then aggregates the results. From your side, this looks like a single test; behind the scenes it's a set of synchronized instances.
The analogy is a flight for hundreds of passengers: no single plane can hold everyone, so you split them into many planes, all flying to the same destination, arriving as one conclusion. The workers are the planes; k6 Cloud is the air traffic control center.
Once the load is distributed, the metrics are distributed too. Practices you should get used to:
http_req_duration: ['p(95)<500'] is evaluated against metrics aggregated from all workers — a single source of truth that makes the cloud test also pass or fail automatically.Rate and Trend metrics are recomputed from the combined set of all instances; define custom metrics with the right type so their aggregation is meaningful.Distributed load testing is not a replacement for local — both serve different needs:
| Scenario | Local | k6 Cloud |
|---|---|---|
| Smoke test / fast development | Most suitable | Overkill |
| Load below tens of thousands of VUs | Adequate | Optional |
| Load from tens to hundreds of thousands of VUs | Not enough | Necessary |
| Traffic from many regions (load zones) | Impossible | Built-in |
| Centralized, shareable results | Limited | Built-in |
| Data must not leave / limited budget | An option | Consider |
The rule of thumb: start local, go cloud only when the load, geography, or need to share results exceeds your machine's capacity. A test that should be 50 VUs doesn't need to pay for cloud workers.
k6 Cloud is convenient, but some teams need full control — for example because data must stay on their own infrastructure. For that there are two self-managed paths:
TestRun Custom Resource to Kubernetes. You describe the test and the number of workers (parallelism), and the operator creates several k6 jobs and synchronizes them:apiVersion: k6.io/v1alpha1
kind: TestRun
metadata:
name: my-load-test
spec:
parallelism: 4
script:
configMap:
name: k6-scripts
file: script.js--execution-segment and --execution-segment-sequence flags. You run several instances in parallel — for example via several CI jobs or pods — each holding a different chunk of VUs, then aggregate their metrics to the same backend (InfluxDB or Prometheus). Flexible, but you're fully responsible for synchronization and aggregation.The choice between managed and self-managed is a trade-off decision: k6 Cloud saves you the orchestration work and includes observability, while k6-operator gives you full ownership of the infrastructure with operational responsibility on your side.
Episode 17 takes k6 beyond the limits of a single machine: from the limits of local execution, getting to know k6 Cloud with k6 login cloud and k6 cloud, understanding load zones and the orchestration of hundreds of thousands of VUs, multi-instance observability practices, to the two self-managed paths (k6-operator and execution segments). You now know how to generate load of any size — from 10 VUs on a laptop to hundreds of thousands of VUs from multiple continents.
Every journey has an end. In episode 18 — the last episode of this series — we solidify production readiness: stable tooling like k6 archive and xk6, features ready for production use, industry trends like performance budgets and shift-left testing, and a full reflection on the 19-episode Learn k6 journey. See you there!