All posts
EngineeringSep 12, 20244 min read

API load testing and performance analysis: Grafana k6 vs Apache JMeter

A side-by-side look at two open-source load testing tools — k6 and JMeter — with example scenarios, result metrics, and when to pick each one.

AT

Apinizer Team

Engineering

API load test scenarios, metrics, and a comparison with k6 and JMeter.

This article explains how to run load tests on APIs — without years of experience — using the open-source tools k6 and JMeter.

  • API — an interface that enables communication between applications.
  • Load testing — tests that evaluate how an application performs under a given load; they measure resilience, speed, and overall performance.
  • k6 — an open-source load-testing tool; JavaScript-based scripts, console-driven. Simulates realistic API traffic and measures how your system responds under load.
  • JMeter — an open-source, Java-based load-testing tool; scenarios are defined via GUI or XML. Simulates realistic user behavior.

We'll run the same kinds of tests with both and compare.

Grafana k6 and Apache JMeter compared

FeatureJMeterk6
Language and styleJavaJavaScript
Setup and startupJRE, GUI-basedNode.js, console-based
Performance and scalabilityHeavy load tests, higher resource useLightweight, scalable
Scenario definitionXML, GUI or manualCode in JavaScript
Distributed testingBroad supportk6 Cloud or custom setups
ReportingGUI, graphs, Grafana / InfluxDBConsole, k6 Cloud, integrations
CommunityLarge user baseRapidly growing

JMeter's UI offers graphical reports, backend listener, and Grafana / InfluxDB. k6 is console-based but pairs with many visualization options and Grafana integration.

k6 basic test scenarios

Examples for load, endurance, stress, and performance-optimization scenarios targeting API endpoints.

Load test

Simulates many users connecting at the same time.

import http from 'k6/http';
import { sleep } from 'k6';
export default function () {
  const numberOfUsers = 100;
  Array.from({ length: numberOfUsers }, (_, index) => {
    http.get(`https://example.com/page${index}`);
    sleep(1);
  });
}

Endurance test

Simulates the application running stably under a constant load for a period.

import http from 'k6/http';
import { sleep } from 'k6';
export default function () {
  while (1) {
    http.get('https://example.com');
    sleep(1);
  }
}

Stress test

Simulates sudden traffic spikes or fast changes in user count.

import http from 'k6/http';
import { sleep } from 'k6';
export default function () {
  const numberOfUsers = __VU * 10;
  Array.from({ length: numberOfUsers }, (_, index) => {
    http.get(`https://example.com/page${index}`);
    sleep(0.1);
  });
}

Example k6 scenario (staged load)

import http from 'k6/http';
import { check, sleep } from 'k6';
export let options = {
  stages: [
    { duration: '30s', target: 500 },
    { duration: '1m', target: 50 },
    { duration: '30s', target: 0 },
  ],
};
export default function () {
  let methods = ['GET', 'POST', 'PUT', 'DELETE'];
  let method = methods[Math.floor(Math.random() * methods.length)];
  let endpoints = [
    'https://example.com/k6_load_test/get',
    'https://example.com/k6_load_test/post',
    'https://example.com/k6_load_test/put',
    'https://example.com/k6_load_test/delete',
  ];
  let endpoint = endpoints[Math.floor(Math.random() * endpoints.length)];
  let res = http.request(method, endpoint);
  check(res, { 'is status 200': (r) => r.status === 200 });
}

Run with k6 run k6_load_test.js.

Result metrics (summary): http_reqs (total requests), http_req_duration (response time), http_req_failed, iterations, vus / vus_max, checks, data_received / data_sent, p(90) / p(95) (percentiles). These help assess your API's behavior under load and find bottlenecks. k6 results can be visualized alongside system metrics via Prometheus and Grafana.

JMeter basic test scenarios

In JMeter you configure Threads (simulated users), Loop count, and Ramp-up Period (time to start all threads).

API performance test. Threads = concurrent requests (e.g. 500); Loop = how many times each user repeats; Ramp-up = time to start all users.

Additional scenarios: (1) increase request count to simulate load, (2) maximum load test, (3) long-duration load test, (4) different request types (GET, POST, PUT, DELETE), (5) average response time test, (6) error-handling test, (7) scheduled tests with a timer.

JMeter can run from the GUI (Run) or from the command line; results can be written to CSV:

jmeter -n -t /path/to/TEST_NAME.jmx -l /path/to/RECORD_NAME.csv

Result metrics (summary): total requests, total time, average requests / second, average / min / max response time, error count and percentage, active / started / finished request counts.

Comparing JMeter and k6 results

FeatureJMeterk6
Test environmentStandalone testLocal environment
Test duratione.g. 2 min 41 se.g. 3 min
Target userse.g. max 500 concurrentRamp up to 500
Total requestse.g. 25,000e.g. 180,077
Average response timee.g. 11.44 se.g. 242 ms
Max response timee.g. 21.15 se.g. 33.68 s
Throughpute.g. 169.6 req / se.g. 857.45 req / s

Values depend on the example test environment.

Conclusion

JMeter supports high concurrent user counts even at lower throughput and is well suited for large-scale applications. k6 offers higher request throughput and is good for minimizing failed-request rates and for scenarios that require fast responses.

Which tool to use depends on your test requirements, target metrics, and application design. Both can be used in different scenarios and provide valuable data for performance testing.

  • #load-testing
  • #k6
  • #jmeter
  • #api-performance
  • #performance-analysis

See it on your cluster

Walk through the platform with us.

A 30-minute tour of Manager, Worker, AI Gateway, and APIops on a Kubernetes of your choice.