k6
Modern load and performance testing from Grafana. Scripts in JavaScript, thresholds in code, giving you automated performance gates on every deploy.
1 The Hook — The NZ Ticket Crash
A popular NZ concert tour went on sale on a Tuesday morning. 15,000 fans hit the site at exactly 9:00 AM. The site, which usually handled 100 users at a time, crashed instantly. The database locked up, the frontend threw "504 Gateway Timeout" errors, and thousands of frustrated fans vented on social media. The company lost tens of thousands in potential sales and significant brand reputation.
The team thought they were ready because the site "felt fast" during testing. But they hadn't performed a Spike Test. With k6, they could have simulated 15,000 concurrent users hitting the site in 30 seconds, identified the database bottleneck, and scaled their infrastructure before the tickets went on sale.
2 The Rule — Performance Budgets (Thresholds)
Performance is a feature. If it's not measured with automated thresholds, it will eventually degrade.
Don't just run a load test and look at the graph. Define Thresholds in your code: "95% of requests must be under 500ms." If the code gets slower, the test fails, and the build breaks.
3 The Analogy — The Bridge Stress Test
The Bridge Weight Limit.
Building a software system is like building a bridge. Functional testing (Selenium/Playwright) checks if the bridge stays up when one car crosses it. Performance testing (k6) checks if the bridge stays up when 1,000 cars try to cross it at the same time during rush hour. You don't want to find out the weight limit when the bridge is already full of people.
4 Watch Me Do It — NZ Government API Spike Test
Scenario: Simulating a sudden surge of traffic to a public rates-payment API.
import http from 'k6/http';
import { check, sleep } from 'k6';
export const options = {
// Define the load "shape"
stages: [
{ duration: '30s', target: 100 }, // Ramp up to 100 users
{ duration: '1m', target: 100 }, // Stay at 100
{ duration: '20s', target: 0 }, // Ramp down
],
// Define performance "gates"
thresholds: {
http_req_duration: ['p(95)<500'], // 95% of requests must be < 500ms
http_req_failed: ['rate<0.01'], // Errors must be < 1%
},
};
export default function () {
const res = http.get('https://api.govt.nz/rates/search?postcode=6011');
// Functional check during load
check(res, {
'is status 200': (r) => r.status === 200,
'has results': (r) => r.json().results.length > 0,
});
sleep(1); // Wait 1s between "user" actions
}
5 Decision Tool — Why k6?
✅ Choose k6 for...
- CI/CD automated performance gates
- API load, stress, and spike testing
- Teams comfortable with JavaScript
- Lightweight, single-binary execution
❌ Choose Others for...
- JMeter: If you need a GUI and complex XML logic
- Lighthouse: For frontend/rendering performance
- Gatling: If your team is purely Scala-based
6 Common Mistakes
🚫 Assuming 200 OK = Success
Mistake: Not using check() to verify the response body.
Why: During a load test, a server might return a 200 OK but send an empty body or an error message inside the JSON. Always check for expected content.
🚫 Testing Against Production
Mistake: Running a 10,000 user load test against your live site.
Why: This is essentially a self-inflicted DDoS attack. Always use a staging environment that matches production specs as closely as possible.
7 Now You Try — Setup
Install k6 on your machine (Windows/Chocolatey):
choco install k6
Run a simple test against the k6 demo site:
k6 run https://test.k6.io
8 Self-Check
Q1. What is a "Spike Test"?
A test that simulates a sudden, extreme surge in traffic (e.g., from 0 to 5,000 users in 10 seconds) to see if the system crashes or scales gracefully.
Q2. Does k6 measure how long a page takes to render in the browser?
No. k6 tests at the protocol level (HTTP). It measures how long the server takes to send the data, but not how long the browser takes to display it. Use Lighthouse for rendering performance.
9 Interview Prep
"How do you integrate performance testing into a CI/CD pipeline?"
Answer: "I use k6 to define Thresholds (SLOs) directly in the test script. For example, I'll set a threshold that the p95 response time must be under 500ms. I then run k6 in a GitHub Action; if the threshold is breached, k6 returns a non-zero exit code, which fails the build and prevents the degraded code from being deployed."
10 Next Step
Fast and functional isn't enough; your app must be secure. Let's look at the standard for automated security scanning: OWASP ZAP.