How-To2026-09-0511 min read

How to Set Up Load Testing in k6

Load testing answers the question that unit tests and integration tests cannot: what happens when hundreds or thousands of users hit your application simultaneously? Without load testing, you discover performance limits in production when real users experience slow responses or outages. k6 is the modern standard for load testing because it uses JavaScript for test scripts, provides excellent metrics out of the box, and runs efficiently from a single machine.

The goal of load testing is not just to find the breaking point — it is to establish performance baselines, validate that changes do not degrade throughput, and verify that your system handles expected traffic with acceptable response times. This guide walks through setting up k6 from installation to CI integration so load testing becomes a regular part of your development cycle.

Step-by-step guide

01

Install k6 and verify the setup

Install k6 using your package manager: brew install k6 on macOS, or download the binary from the k6 releases page. Verify the installation with k6 version. Create a test directory in your project (e.g., load-tests/) and add a basic script that makes a single HTTP GET request. Run it with k6 run script.js to confirm everything works. k6 outputs built-in metrics including request duration, failure rate, and throughput automatically.

  • Install k6 via Homebrew or binary download
  • Create a load-tests/ directory in your project
  • Write and run a minimal test to verify the installation
02

Write test scripts that simulate real user behavior

A realistic load test simulates user workflows, not just endpoint hammering. Write a k6 script that performs a complete user flow: authenticate, navigate to a dashboard, load data, perform an action, and verify the response. Use k6's group() function to organize steps and add think time with sleep() between actions to simulate human pacing. A test with no think time creates unrealistic burst traffic that does not match production patterns.

03

Configure load stages with ramping virtual users

Define your load profile using k6's stages option in the script's options export. Start with a ramp-up phase (0 to target VUs over 2 minutes), a sustained phase (hold at target VUs for 10 minutes), and a ramp-down phase (target VUs to 0 over 1 minute). This pattern simulates real traffic growth, gives the system time to warm up, and provides a sustained period for meaningful metric collection. Start with 50 VUs and increase in subsequent runs.

  • Set ramp-up stage to gradually increase from 0 to your target VUs
  • Set a sustained stage holding at target VUs for 5-10 minutes
  • Set a ramp-down stage to gracefully reduce load
04

Define performance thresholds for pass/fail criteria

Add thresholds to your script's options that define what good looks like. Common thresholds include: p(95) response time under 500ms, p(99) under 2 seconds, error rate under 1%, and throughput above a minimum requests per second. When a threshold is violated, k6 exits with a non-zero code, which makes it CI-friendly. Thresholds turn load testing from a manual observation exercise into an automated quality gate.

05

Add custom metrics and tags for detailed analysis

Use k6's custom metrics API to track business-specific measurements beyond the built-in HTTP metrics. Create a Trend metric for database query time if your API returns it in response headers, or a Counter for specific business events like successful checkouts. Add tags to HTTP requests (e.g., endpoint name, user type) so you can filter metrics by API route or user segment in the results output.

06

Integrate k6 into your CI pipeline

Add a GitHub Actions workflow that runs your load test against a staging environment on every merge to main or on a nightly schedule. Configure the workflow to run k6 with your threshold options and fail the build if thresholds are violated. Store the results output as an artifact for investigation. For dashboarding, pipe k6 output to Grafana Cloud k6 or InfluxDB + Grafana so you can track performance trends over time.

Common mistakes

Running load tests against production without warning

Load tests generate significant artificial traffic. Running them against production without coordinating with your infrastructure team can trigger alerts, affect real users, or hit rate limits. Always run against a staging environment that mirrors production or coordinate a production test window with the team.

Testing a single endpoint in isolation

Hammering one endpoint does not simulate real usage. Real traffic hits multiple endpoints with different frequencies. Your authentication endpoint might handle 10x more requests than your export endpoint. Model your load test on actual traffic patterns from your access logs.

Not including think time between requests

A script that fires requests back-to-back without sleep() creates an artificial spike that no real user base would generate. Add realistic think time (1-5 seconds between actions) to simulate actual user pacing. This also prevents your test from being limited by client-side CPU rather than server capacity.

Ignoring the ramp-up phase

Jumping instantly from 0 to 500 VUs creates a thundering herd that tests your system's cold-start behavior, not its steady-state performance. Ramp up gradually to let connection pools fill, caches warm, and auto-scaling respond. The steady-state phase is where your meaningful performance data comes from.

Tips

Use k6's scenarios feature to model multiple user types simultaneously — for example, 80% browse-only users and 20% users performing write operations — for a more realistic traffic mix.

Export k6 results to Grafana Cloud using the built-in k6 cloud integration for historical trend analysis and team-accessible dashboards.

Start with a baseline test at low VUs to establish performance expectations, then gradually increase to find the inflection point where response times degrade.

Use k6 browser module for load testing that includes real browser rendering, which catches frontend performance issues that API-level load tests miss.

How Vantage helps

Vantage generates tickets with technical context that includes non-functional requirements like performance targets. When a PRD specifies response time SLAs, the generated tickets include performance acceptance criteria that map directly to k6 thresholds, ensuring performance testing is part of the definition of done.

Frequently asked questions

Spend less time on setup, more on decisions

Vantage connects your tools and generates specs grounded in real data. Free to start.

Free to start. No credit card required.

Related reading