Skip to content

Split View: 로드/성능 테스트 도구 2026 — k6·Locust·Vegeta·Gatling·Artillery·JMeter 심층 비교 (JMeter 너머의 풍경)

|

로드/성능 테스트 도구 2026 — k6·Locust·Vegeta·Gatling·Artillery·JMeter 심층 비교 (JMeter 너머의 풍경)

프롤로그 — "초당 만 건 가능합니다"라는 거짓말

2026년 어느 회사의 출시 전날.

PM: "초당 만 건 가능하죠?" 백엔드: "JMeter로 돌려봤습니다. 통과했어요." SRE: "어떤 시나리오로?" 백엔드: "constant 만 RPS로 5분..." SRE: "production traffic 패턴은요? warm-up이 들어갔어요? p99는?" 백엔드: "..."

이 장면이 2026년에도 흔하다. 도구는 좋아졌는데 측정 문화는 그대로다. "통과했다"라고 말하지만, 무엇이 통과했는지, 어떤 분포에서 통과했는지, production과 얼마나 닮았는지는 답이 없다. 그러는 사이 출시 후 실제 트래픽은 burst로 들어오고, 캐시가 콜드 상태에서 시작하고, p99는 SLO를 깨고, 그 모든 게 "통과한" 테스트와 무관하게 일어난다.

도구 자체는 좋아졌다. 2010년대의 JMeter 중심 세계는 이제 k6(Grafana) 가 사실상 표준이 된 풍경으로 바뀌었고, Locust·Vegeta·Gatling·Artillery·Bombardier 같은 선택지가 각자의 영역에서 자리를 잡았다. 마이크로 벤치마크 영역에는 wrk·wrk2·autocannon이 살아 있고, gRPC·WebSocket 같은 비-HTTP 프로토콜에는 ghz·fortio가 따로 있다.

이 글은 2026년의 로드/성능 테스트 도구 지도를 그린다. 각 도구의 위치, 같은 시나리오를 도구별로 어떻게 짜는지, "좋은 로드 테스트"란 무엇인지, 그리고 우리 팀이 어떻게 고를지까지.


1장 · 로드 테스트의 4가지 목적 — 무엇을 잴 건지부터

도구를 고르기 전에 목적부터 정리한다. 같은 도구가 모든 목적에 맞지 않는다.

  1. 마이크로 벤치마크 (micro-benchmark) — 단일 엔드포인트의 한계 throughput과 p99 latency를 잰다. "이 핫 패스가 얼마나 빠른가?" 작은 변경의 회귀를 잡는 용도. wrk, autocannon, Bombardier, Vegeta.
  2. 부하 테스트 (load test) — 예상 트래픽 수준에서 시스템이 SLO 안에서 동작하는가. 보통 일정 RPS를 일정 시간 유지. k6, Locust, Gatling, Artillery, JMeter.
  3. 스트레스 테스트 (stress test) — 한계를 찾는다. 어느 지점에서 시스템이 무너지는가, 어떻게 무너지는가, 회복 가능한가. 위 도구들 + 시나리오 설계.
  4. 스파이크/소크 테스트 (spike & soak) — 갑작스러운 트래픽 폭증(스파이크)과 장시간 유지(소크, 메모리 누수·연결 누수 잡기). k6, Locust가 시나리오 표현에 강하다.

추가로 카오스 테스트(장애 주입 + 부하)는 별도의 축이지만, 부하 도구로 트래픽을 흘리며 chaos tool로 장애를 주입하는 조합이 흔하다.

핵심: "성능 테스트"라는 단일 단어가 위의 4가지를 모두 가리킨다. 도구를 고를 때는 "어떤 종류의 테스트를 주로 할 것인가"부터 답해야 한다. 마이크로 벤치마크에 JMeter를 끄집어내는 건 과하고, 복잡한 시나리오에 wrk를 쓰는 건 부족하다.


2장 · 도구 지도 2026 — 한눈에

도구언어/스크립트강점약점대표 사용처
k6JS (ES2015+), Go 런타임모던 기본값, 풍부한 출력, 클라우드 옵션, gRPC/WS/브라우저분산은 OSS에서 직접 구성2026년의 일반 기본값
LocustPython분산이 쉽다, Python 코드 가능단일 워커 throughput 한계Python 팀, 행위 모델 복잡
VegetaGo (CLI + 라이브러리)한 줄로 실행, 결과 분석 강력시나리오 표현은 단순HTTP 마이크로 벤치, 빠른 측정
GatlingScala/Java DSL시나리오 표현력, 엔터프라이즈 리포팅Scala 학습 곡선대규모, JVM 친화 조직
ArtilleryNode.js, YAML빠른 시작, YAML로 표현고부하에서 단일 노드 한계Node 팀, CI 시나리오
wrk / wrk2C, Lua 스크립트매우 가볍고 빠른 HTTP 벤치HTTP만, 시나리오 단순핫 패스 마이크로 벤치
autocannonNode.jsnpm 설치만으로 즉시Node 팀 외에는 동기 약함Node API 빠른 벤치
BombardierGo정말 단순하고 빠른 CLI시나리오 거의 없음한 줄 부하 측정
JMeterJava, GUI/XML오래된 자료·플러그인 생태계XML 시나리오, 모던 UX 아님엔터프라이즈, 기존 자산
ghzGo, CLIgRPC 전용, 단순gRPC 외에는 부적합gRPC 서비스 벤치
fortioGo (Istio)gRPC + HTTP, 분포 분석UI 평이서비스 메시 검증

한 줄 정리: 2026년의 "처음 잡는 도구"는 대체로 k6다. 팀이 Python 친화적이면 Locust. 한 줄 마이크로 벤치는 Vegeta(또는 wrk). 엔터프라이즈/JVM 친화 조직과 기존 자산은 JMeter/Gatling. Node 친화 팀의 빠른 CI 시나리오는 Artillery. gRPC는 ghz 또는 k6 gRPC 모듈.


3장 · k6 — 2026년의 일반 기본값

현재 상태 (2026년 5월): Grafana Labs 산하. k6 OSS 바이너리는 무료, Grafana Cloud k6에서 분산 실행/대시보드를 유료로 제공. v0.5x 대 안정 릴리스가 꾸준히 나오고 있으며, browser 모듈(Playwright 백엔드)·gRPC·WebSocket·xk6 확장 생태계가 확장 중이다.

왜 기본값이 됐나:

  • JS로 시나리오 작성 — 엔지니어 다수가 읽고 짤 수 있다.
  • Go 기반 단일 바이너리 — 설치가 쉽다. CPU 효율도 좋다 (Locust보다 단일 워커 throughput이 훨씬 높다).
  • 출력이 풍부 — 콘솔에서 p50/p90/p95/p99까지 기본으로 본다. Prometheus·InfluxDB·Datadog로 export 가능.
  • scenario·executor 모델constant-vus, ramping-arrival-rate, per-vu-iterations 등 표현력이 좋다.
  • 확장 가능 — xk6로 SQL·Kafka·Redis 모듈을 붙일 수 있다.

기본 스크립트 (4장에서 비교용으로 다시 본다):

// k6 script: login + ramp 50 → 200 RPS for 5min
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  scenarios: {
    login_ramp: {
      executor: 'ramping-arrival-rate',
      startRate: 50,
      timeUnit: '1s',
      preAllocatedVUs: 50,
      maxVUs: 500,
      stages: [
        { target: 50, duration: '1m' },
        { target: 200, duration: '5m' },
        { target: 200, duration: '2m' },
      ],
    },
  },
  thresholds: {
    http_req_duration: ['p(99)<500'],
    http_req_failed: ['rate<0.01'],
  },
};

export default function () {
  const res = http.post('https://api.example.com/login', JSON.stringify({
    user: 'demo',
    pass: 'pw'
  }), { headers: { 'Content-Type': 'application/json' } });
  check(res, { 'status 200': (r) => r.status === 200 });
  sleep(1);
}

k6 Cloud(Grafana Cloud k6) 비용 감각 (2026년 기준): 무료 플랜은 월 50 VUh, Pro 플랜은 $299/월 부터 시작하며 VUh와 동시 실행 한도가 늘어난다. 분산 실행/지역 분산이 필요하면 cloud 옵션이 편하고, 대안은 self-host 분산(여러 노드에서 같은 스크립트 실행, 결과 집계).

한계:

  • 분산 실행이 OSS에서는 직접 구성해야 한다 — k8s operator(grafana/k6-operator)가 있지만 운영 부담.
  • JS 런타임은 V8이 아니라 Goja(Go에서 임베드된 ES5+). 일부 모던 JS feature는 babel transform 필요.
  • 데이터 변환 무거운 로직은 시나리오 외부에서 처리하는 게 안전.

4장 · 같은 시나리오, 도구별 비교 — POST /login + ramp 50 → 200 RPS

같은 시나리오를 k6 / Locust / Vegeta로 어떻게 표현하는지 나란히 본다.

k6

위 3장의 스크립트 그대로. 핵심은 ramping-arrival-rate executor와 thresholds로 p99·실패율을 코드로 선언.

Locust (Python)

# locustfile.py
from locust import HttpUser, task, LoadTestShape, constant_throughput

class LoginUser(HttpUser):
    wait_time = constant_throughput(1)  # 1 req/sec per user

    @task
    def login(self):
        self.client.post(
            "/login",
            json={"user": "demo", "pass": "pw"},
            headers={"Content-Type": "application/json"},
        )

class RampShape(LoadTestShape):
    stages = [
        {"duration": 60, "users": 50, "spawn_rate": 50},
        {"duration": 360, "users": 200, "spawn_rate": 5},
        {"duration": 480, "users": 200, "spawn_rate": 0},
    ]

    def tick(self):
        run_time = self.get_run_time()
        for stage in self.stages:
            if run_time < stage["duration"]:
                return (stage["users"], stage["spawn_rate"])
        return None

실행: locust -f locustfile.py --headless -H https://api.example.com. 분산 모드는 master/worker(--master, --worker)로 쉽게 분리되며, k8s helm chart도 잘 알려져 있다.

Vegeta (CLI)

# targets.txt
# POST https://api.example.com/login
# Content-Type: application/json
# @body.json

# step 1: 50 RPS for 1m
echo "POST https://api.example.com/login" | \
  vegeta attack -rate=50 -duration=60s -body=body.json \
                -header="Content-Type: application/json" \
  | vegeta report -type=hist[0,100ms,200ms,500ms,1s]

# step 2: 200 RPS for 5m
echo "POST https://api.example.com/login" | \
  vegeta attack -rate=200 -duration=5m -body=body.json \
                -header="Content-Type: application/json" \
  | tee result.bin \
  | vegeta report
vegeta plot result.bin > plot.html

Vegeta는 시나리오 자체가 단순하다 — 일정 rate를 일정 시간 동안 친다. ramp는 보통 단계별 명령을 이어 실행하거나, 셸 스크립트로 외부에서 만든다. 그 단순함이 강점이다 — 한 줄로 측정이 끝나고, vegeta report -type=json이나 vegeta plot으로 분포·시계열을 본다.

비교 관찰:

  • 표현력: Locust(가장 자유) ≈ k6 > Vegeta. Vegeta는 일부러 단순하다.
  • CPU 효율: k6 > Vegeta > Locust (단일 워커 기준; Locust는 분산으로 보완).
  • CI 친화: k6(threshold로 exit code) ≈ Vegeta(report로 grep). Locust도 headless로 CI 가능.
  • 결과 시각화: k6(Grafana Cloud k6 또는 직접 Prometheus) > Locust(웹 UI) > Vegeta(plot HTML).

5장 · Locust — Python 팀의 편안한 친구

현재 상태 (2026년): 활발히 유지보수 중. v2.x 안정. Locust는 "코드로 표현 가능한 행위 모델"이 강점이다. 사용자가 무엇을 하는지 클래스/메서드로 표현하고, @task 데코레이터로 가중치를 준다.

언제 적합한가:

  • 팀이 Python 친화적이고 데이터/추상화 라이브러리를 그대로 부르고 싶을 때.
  • 사용자 행위 모델이 복잡할 때(여러 페이지를 순회, 상태 보유).
  • 분산 실행이 필요하지만 별도 SaaS는 쓰기 싫을 때 — --master/--worker로 매우 단순.

한계:

  • 단일 워커의 throughput은 k6보다 낮다. Python의 gevent 기반 동시성은 효율적이지만 Go보다는 무겁다.
  • 결과 시각화는 내장 웹 UI가 있지만 k6/Grafana 조합만큼 풍부하지 않다.

: Locust의 강점은 분산이 쉽다는 것이다. 100k+ RPS가 필요하면 워커 수십 개를 띄우는 게 자연스럽다. k8s에 helm chart로 띄우고, Prometheus로 메트릭 모으는 패턴이 익숙해지면 운영이 단순해진다.


6장 · Vegeta — 한 줄의 우아함

현재 상태 (2026년): 단일 메인테이너 중심으로 유지보수 중. 안정적이고 단순하다. 신기능은 거의 없지만, 그게 미덕이다.

왜 Vegeta가 살아남았나:

  • 한 줄로 측정echo "GET https://..." | vegeta attack -rate=100 -duration=30s | vegeta report. 다른 도구라면 파일 만들고, runner 띄우고, 컨테이너 마운트하는 게 vegeta는 한 줄이다.
  • 분포 분석이 정확vegeta report 출력에 p50/p90/p95/p99/min/mean/max가 한 번에 나온다. histogram 버킷도 CLI로 지정.
  • 결과 직렬화.bin 형식으로 저장 후 나중에 reproc 가능. CI에서 bin을 artifact로 저장하고 나중에 분석.

한계:

  • 시나리오 표현이 단순하다 — 일정 rate 또는 step 묶음. 복잡한 사용자 시뮬레이션엔 부적합.
  • 분산 모드는 CLI 도구다 보니 직접 구성. 보통 여러 머신에서 같은 명령을 실행하고 bin을 모아 합치는 방식.

대표 사용: 핫 패스 하나의 latency 분포를 정확히 측정하고 싶을 때, CI에서 회귀를 잡는 마이크로 벤치, "지금 서버가 살아 있나" 빠른 체크.


7장 · Gatling — JVM 진영의 강자

현재 상태 (2026년): Gatling 3.x 안정. Gatling Enterprise(유료, 구 FrontLine)와 OSS 둘 다 활발. Scala DSL이 기본이지만 Java/Kotlin DSL도 정식 지원한다.

왜 여전히 쓰이나:

  • DSL의 표현력 — 시나리오·체이닝·assertion이 코드처럼 자연스럽다.
  • 리포팅 — HTML 리포트가 매우 깔끔하다. enterprise는 분산/팀 협업.
  • JVM 친화 조직 — Maven/Gradle 빌드에 자연스럽게 들어간다.
  • Scala 학습 비용은 줄었다 — Java DSL이 1급 시민이 됐다.

언제 적합한가:

  • JVM 기반 백엔드를 가진 조직, 빌드 시스템에 통합하고 싶을 때.
  • 시나리오가 복잡하고 코드 리뷰 가능한 형태로 두고 싶을 때.
  • 엔터프라이즈 지원이 필요한 환경.

한계:

  • 가벼운 한 줄 측정은 부적합 — JVM 기동·SBT/Maven 비용.
  • Scala 진입 장벽은 줄었지만 0은 아니다.

8장 · Artillery — YAML 시나리오의 간편함

현재 상태 (2026년): OSS + Cloud(유료). YAML로 시나리오를 표현하는 게 매력. 최근 v2 부터는 분산 실행(Cloud) 옵션도 강화됐다.

왜 쓰이나:

  • YAML 시나리오 — 코드 작성 없이 "URL·페이로드·플로우"를 선언적으로.
  • Node.js 기반 — Node 팀에 친숙.
  • 빠른 시작npm install -g artillery 후 yml 파일 하나면 실행.

한계:

  • 단일 노드 throughput은 k6보다 낮다 (Node 이벤트 루프 한계).
  • 매우 큰 부하에선 Cloud 또는 다중 인스턴스가 필요.

예시 시나리오 (조금 다른 형태로):

config:
  target: 'https://api.example.com'
  phases:
    - duration: 60
      arrivalRate: 50
    - duration: 300
      arrivalRate: 50
      rampTo: 200
    - duration: 120
      arrivalRate: 200
scenarios:
  - flow:
      - post:
          url: '/login'
          json:
            user: 'demo'
            pass: 'pw'
          expect:
            - statusCode: 200

9장 · JMeter — 살아 있는 노장

현재 상태 (2026년): Apache JMeter 5.x 유지보수 중. 학습 자료가 가장 많고, 플러그인 생태계가 가장 넓다. GUI 중심이지만 헤드리스 실행도 정식 지원.

왜 여전히 보이나:

  • 기존 자산 — 수많은 조직이 .jmx 파일을 갖고 있다. 마이그레이션 비용 vs. 유지 비용.
  • 플러그인 — Prometheus listener, custom protocol, blazemeter 통합 등.
  • 금융·통신 등 엔터프라이즈 — 사내 표준이 JMeter인 경우.
  • GUI 친화 — 코드를 모르는 QA가 쓰기 좋다 (장단 양면).

왜 새로 시작하는 팀은 거의 안 고르나:

  • XML(.jmx) 시나리오 — git diff 친화적이지 않다.
  • 모던 UX·CLI 친화가 약하다.
  • CI 통합이 가능하지만 k6/Locust에 비해 손이 더 간다.

가이드: 신규 프로젝트에서 JMeter를 새로 선택할 이유는 거의 없다. 다만 기존 자산이 있다면 그것을 폐기하고 마이그레이션하는 비용은 별도 결정. 점진적으로 새 테스트는 k6/Gatling으로 짜고, 기존은 유지하는 패턴이 흔하다.


10장 · 마이크로 벤치마크 — wrk / wrk2 / autocannon / Bombardier

이 4개 도구는 "한 엔드포인트의 한계 throughput과 latency 분포"를 빠르게 잡는 데 특화됐다.

wrk

  • C로 작성, 매우 빠르다. Lua 스크립트로 약간의 커스터마이즈.
  • HTTP만, keep-alive 친화.
  • 단점: rate-limit이 없다 — 한계 throughput을 측정하므로 항상 max 부하.

wrk2

  • wrk의 fork. 고정 rate를 지원 — "정확히 1000 RPS를 30초 동안" 같은 측정 가능.
  • 마이크로 벤치 + 고정 rate 측정에 이상적.
  • coordinated omission 보정에 강점.

autocannon

  • Node.js 기반. npm install -g autocannonautocannon -c 50 -d 30 https://....
  • Node 친화 팀의 빠른 CI 벤치에 적합.

Bombardier

  • Go 단일 바이너리. 매우 단순하고 빠르다. bombardier -c 125 -n 1000000 https://....
  • 시나리오 표현 거의 없지만, 그게 핵심.
  • 메인테이너 활동은 있지만 신기능보다는 안정 유지 모드.

언제 무엇을:

  • 정확한 latency 분포와 고정 rate가 필요 → wrk2.
  • 그냥 빠르게 한 번 부하 → wrk 또는 Bombardier.
  • Node 팀이고 CI 통합 → autocannon.
  • 시나리오가 조금이라도 필요 → 이 4개가 아니라 Vegeta 또는 k6.

11장 · 비-HTTP 프로토콜 — gRPC, WebSocket, 브라우저

2026년의 부하 측정은 HTTP만이 아니다. gRPC·WebSocket·실 브라우저(Headless Chrome) 모두 측정 대상이다.

gRPC

  • ghz — gRPC 전용 CLI 도구. ghz --insecure --proto ./svc.proto --call svc.Hello -c 50 -n 10000 .... 단순하고 정확.
  • k6 gRPC 모듈import grpc from 'k6/net/grpc'. 시나리오 안에 gRPC 호출을 섞을 수 있다.
  • fortio — Istio 출신. HTTP + gRPC 둘 다, p50–p999 분포 분석에 강하다.

WebSocket

  • k6 WS 모듈import ws from 'k6/ws'. 연결 수·메시지 RPS·세션 길이 시나리오 가능.
  • Artillery — WS를 기본 지원, YAML로 시나리오.
  • Gatling — WS 시나리오 표현력이 좋음.

브라우저 (Real Browser Load)

  • k6 browser 모듈 — Playwright 백엔드. 실제 브라우저로 JS 실행·렌더·페이지 상호작용을 측정. 사용 사례: 프런트엔드 회귀, 페이지 로드 SLO.
  • 비용 주의: 브라우저 인스턴스는 무거우므로 RPS가 아니라 동시 세션 수로 사고.

12장 · "좋은 로드 테스트"란 무엇인가 — 2026 체크리스트

도구가 좋아도 시나리오가 나쁘면 결과도 나쁘다. 좋은 로드 테스트의 핵심.

1) production-like 데이터

  • 사용자 ID, 페이로드 크기, 토큰 분포가 production과 닮아야 한다.
  • "한 사용자가 같은 페이지를 1만 번"은 캐시에 다 맞는다 — production은 그렇지 않다.
  • production에서 sampling한 페이로드를 anonymize해서 사용하는 패턴.

2) 일정 rate가 아니라 분포

  • "constant 1000 RPS"는 measurement용이지 reality와 멀다.
  • production은 burst·dip·diurnal 패턴이 있다.
  • k6의 ramping-arrival-rate, Locust의 LoadTestShape로 시나리오를 모델링.

3) warm-up과 ramp-up

  • 캐시·DB connection pool·JIT가 콜드 상태로 시작하는 측정은 항상 비관적이다.
  • 처음 1–2분은 warm-up으로 두고 측정 구간에서 제외.

4) p99 (avg 아님)

  • "평균 latency"는 SLO의 친구가 아니다. 평균은 long-tail을 숨긴다.
  • p95·p99·p999 (특히 p99)가 SLO와 직결된다. 모든 도구의 출력에서 percentile을 확인.
  • 측정 도구가 coordinated omission으로 p99를 낮게 보고할 수 있다 — wrk2가 이 문제를 처음 잘 다뤘다.

5) error rate 분리

  • 성공 응답만으로 latency를 잡으면 죽은 요청을 못 본다.
  • 4xx·5xx·timeout·connection refused를 따로 카운트하고, 임계치를 설정.

6) 다중 측정점

  • 부하 도구의 클라이언트 측 latency뿐 아니라 서버 측 RED(Rate·Error·Duration) 메트릭, downstream 의존성도 함께 본다.
  • 부하 도구가 "느림"을 보고하는데 서버 메트릭은 빠르다 → 네트워크/측정 문제. 그 반대도 있다.

7) 한 번 말고 정기적

  • 출시 전 한 번이 아니라, 주간·월간 회귀 테스트로 둔다.
  • 코드 변경이 latency 분포에 미친 영향을 시계열로.

13장 · self-host 대 cloud — 비용과 운영

분산 실행이 필요해지면 두 갈래다.

Self-host 분산

  • k6 OSS + grafana/k6-operator (k8s) — pod로 실행, 결과를 Prometheus/InfluxDB로.
  • Locust master/worker — 가장 단순. helm chart로 워커 N개 띄움.
  • 여러 노드에서 같은 명령 + 결과 머지 — vegeta·wrk·Bombardier 식 접근.

장점: 비용 통제, 데이터가 인하우스. 단점: 운영 부담, 지역 분산 어려움.

Cloud

  • Grafana Cloud k6 — 분산 실행, 지역, 대시보드. 월 $299 부터.
  • BlazeMeter — JMeter/Gatling/k6 호환, 엔터프라이즈 SaaS.
  • Artillery Cloud — Artillery 기반 SaaS.
  • Loader.io, k6 Cloud — 작은 부하 측정용 무료 티어부터.

장점: 지역 분산·즉시 실행·대시보드 즉시. 단점: 비용(주 1회 큰 테스트면 빠르게 $수백~수천/월).

경험칙: 단발성 대형 측정(출시 전)은 cloud가 싸고 빠르다. 정기 회귀 테스트는 self-host가 장기적으로 싸다. 둘을 섞는 조직이 많다 — 일상 CI는 self-host, 분기별 대규모는 cloud.


14장 · 도구를 고르는 결정 프레임 — 정직한 가이드

상황추천
처음 시작, 일반 백엔드k6
Python 팀, 행위 모델 복잡Locust
한 줄 마이크로 벤치Vegeta 또는 wrk2
Node 팀, CI 빠르게Artillery 또는 autocannon
엔터프라이즈 JVM 조직Gatling
기존 자산이 JMeterJMeter 유지 + k6 신규 병행
gRPC 측정ghz 또는 k6 gRPC
브라우저 부하k6 browser
단순 throughput 한계 측정wrk 또는 Bombardier
카오스 테스트 + 부하k6/Locust + Toxiproxy/Litmus

섞기는 흔하다. 한 조직 안에서 마이크로 벤치는 Vegeta, 일반 부하는 k6, 기존 큰 시나리오는 JMeter — 이런 조합이 현실의 모습. 도구를 통일하려고 무리하지 말고, 영역별로 적합한 도구를 인정하는 게 운영을 단순하게 한다.


15장 · 안티패턴과 함정

  • production에서 직접 부하 테스트 — staging 또는 격리된 production-like 환경에서 한다. production canary는 별개 기법.
  • DNS·CDN을 통과하지 않고 origin에 직접 — 측정은 통과하지만 SLO는 CDN 포함이다. 측정 경로가 user path와 같아야 한다.
  • localhost에서 측정 후 결론 — 네트워크 latency가 0이라 RPS만 보면 거짓 안전감.
  • constant rate 한 번으로 통과 선언 — production은 분포다.
  • 평균 latency만 본다 — p99를 봐야 한다.
  • 부하 도구만 본다 — 서버 메트릭과 함께 본다.
  • 출시 전 한 번 — 회귀 테스트로 둬야 한다.
  • wrk로 시나리오 측정 — 시나리오는 wrk의 일이 아니다.
  • 분산 안 짜고 단일 노드로 100k RPS 시도 — 도구의 한계를 시스템 한계로 오인.

에필로그 — 측정은 결정의 도구다

도구는 풍부하다. JMeter가 표준이던 시절은 갔고, k6가 사실상 기본값이 됐다. Locust는 Python 친화 조직의 좋은 친구, Vegeta는 한 줄 측정의 우아함, Gatling은 JVM 진영의 강자, Artillery는 빠른 시작, wrk/wrk2/autocannon/Bombardier는 마이크로 벤치의 단순함.

그러나 도구가 결과를 만들지는 않는다. 시나리오가 production을 닮았는가, percentile을 보았는가, warm-up을 두었는가, 회귀로 두었는가가 결과를 만든다. 도구를 고른 후의 일이 더 길고 중요하다.

이 글의 한 문장 요약: "잘 돌아요"는 측정이 아니다. p99·분포·시나리오로 답해야 측정이다. 도구는 그 답을 가능하게 하는 수단일 뿐, 답 자체는 우리가 정의해야 한다.

12개 항목 체크리스트

  1. 목적이 명확한가 (마이크로/부하/스트레스/스파이크 중)?
  2. production-like 데이터를 쓰는가?
  3. constant rate 말고 분포·ramp를 모델링했는가?
  4. warm-up 구간을 측정에서 제외했는가?
  5. p99(또는 p999)를 SLO에 연결했는가?
  6. error rate를 latency와 분리해서 보았는가?
  7. 클라이언트 측 + 서버 측 메트릭을 같이 보았는가?
  8. CI에 회귀로 들어가 있는가?
  9. 분산이 필요할 때 self-host/cloud 결정을 내렸는가?
  10. 비-HTTP 프로토콜이 있다면 그 도구를 함께 쓰는가 (gRPC/WS/브라우저)?
  11. 측정 경로가 user path와 일치하는가 (DNS·CDN 포함)?
  12. coordinated omission 보정을 이해하고 있는가?

안티패턴 10가지

  1. 평균 latency만 본다 — p99를 보라.
  2. constant rate 한 번으로 통과 선언 — 분포를 모델링.
  3. localhost에서 측정 후 결론 — 네트워크가 없다.
  4. production에서 직접 부하 — staging에서.
  5. 부하 도구만 본다 — 서버 메트릭과 함께.
  6. 출시 전 한 번 — 정기 회귀로.
  7. JMeter로 모든 걸 한다 — 영역별로 도구를.
  8. 분산 안 짜고 단일 노드로 무리 — 도구 한계 ≠ 시스템 한계.
  9. warm-up 무시 — 초반 데이터가 결론을 왜곡.
  10. error rate 누락 — 죽은 요청을 못 본다.

다음 글 예고

다음 글 후보: production에서 신호와 노이즈 — RED·USE·SLO 대시보드 설계, chaos engineering 2026 — Litmus·Chaos Mesh·Gremlin·AWS FIS 비교, performance regression CI — 한 줄에서 분포까지.

"측정 가능한 것이 개선 가능한 것이다. 그리고 분포를 보지 않으면 측정이 아니다."

— 로드/성능 테스트 도구 2026, 끝.


참고 / References

Load/Performance Testing Tools 2026 — Deep Dive on k6, Locust, Vegeta, Gatling, Artillery, JMeter (Beyond JMeter)

Prologue — "We can do 10k RPS" is usually a lie

Some company, the night before launch in 2026.

PM: "We can do 10k RPS, right?" Backend: "I ran it in JMeter. It passed." SRE: "What scenario?" Backend: "Constant 10k RPS for 5 minutes..." SRE: "What about the production traffic pattern? Did you do warm-up? What's p99?" Backend: "..."

This scene is still common in 2026. The tools got better; the measurement culture did not. "It passed" is the phrase, but what passed, under what distribution, how close to production — nobody answers. Then real traffic arrives in bursts, caches start cold, p99 breaks the SLO, and none of it correlates with the test that "passed."

The tools themselves have improved. The JMeter-centric world of the 2010s has shifted to one where k6 (Grafana Labs) is the de facto default, with Locust, Vegeta, Gatling, Artillery, and Bombardier each holding their own ground. wrk, wrk2, and autocannon are alive and well in the micro-benchmark niche, and non-HTTP protocols like gRPC and WebSocket have their own homes in ghz and fortio.

This post maps the 2026 landscape of load/performance testing tools. Where each tool sits, how the same scenario looks across them, what "a good load test" actually means, and how to pick honestly for your team.


1. Four purposes of load testing — name the target first

Before picking a tool, name the purpose. The same tool doesn't fit every purpose.

  1. Micro-benchmark — peak throughput and p99 latency of a single endpoint. "How fast is this hot path?" Good for catching regressions on small changes. wrk, autocannon, Bombardier, Vegeta.
  2. Load test — does the system stay inside SLO at the expected traffic level. Usually a steady RPS for some time. k6, Locust, Gatling, Artillery, JMeter.
  3. Stress test — find the limit. Where does it break, how does it break, can it recover. Same tools plus scenario design.
  4. Spike & soak — sudden surges (spike) and long runs (soak — catches memory or connection leaks). k6 and Locust express these scenarios well.

A fifth axis is chaos testing — injecting failure while traffic flows — usually a combination of a load tool and a chaos tool.

The core insight: "performance testing" is one phrase covering four different things. Pick your tool only after answering "what kind am I doing most often?" Dragging out JMeter for a micro-benchmark is overkill; using wrk for a complex scenario is undershooting.


2. Tool map 2026 — one table

ToolLanguage/scriptStrengthsWeaknessesTypical use
k6JS (ES2015+), Go runtimeModern default, rich output, cloud option, gRPC/WS/browserDistributed runs need setup in OSSThe general default in 2026
LocustPythonEasy distributed mode, full Python codeSingle-worker throughput limitedPython teams, complex user models
VegetaGo (CLI + lib)One-liner runs, strong result analysisSimple scenarios onlyHTTP micro-bench, quick checks
GatlingScala/Java DSLScenario expressiveness, enterprise reportsScala learning curveLarge, JVM-friendly orgs
ArtilleryNode.js, YAMLFast start, declarative YAMLSingle-node limits at high loadNode teams, CI scenarios
wrk / wrk2C, Lua scriptingVery light, very fast HTTP benchHTTP only, simple scenariosHot-path micro-bench
autocannonNode.jsnpm install and goMostly fits Node teamsQuick Node API bench
BombardierGoDead-simple, fast CLIAlmost no scenarioOne-liner load checks
JMeterJava, GUI/XMLOld library and plugin ecosystemXML scenarios, dated UXEnterprise, legacy assets
ghzGo, CLIgRPC-only, simplegRPC onlygRPC service benchmarks
fortioGo (Istio)gRPC + HTTP, distribution analysisPlain UIService mesh validation

One-liner: in 2026, the "tool you pick up first" is usually k6. Python-friendly teams pick Locust. Vegeta (or wrk) for one-liner micro-benches. JMeter/Gatling for enterprise/JVM orgs and legacy assets. Artillery for Node teams in CI. gRPC goes to ghz or k6's gRPC module.


3. k6 — the 2026 default

Status (May 2026): under Grafana Labs. The k6 OSS binary is free; Grafana Cloud k6 is the paid option for distributed runs and dashboards. v0.5x stable releases ship steadily; the browser module (Playwright backend), gRPC, WebSocket, and the xk6 extension ecosystem continue to grow.

Why it became the default:

  • JS-scriptable — most engineers can read and write it.
  • Single Go binary — easy to install, CPU-efficient (much higher single-worker throughput than Locust).
  • Rich output — p50/p90/p95/p99 in the console by default. Exports to Prometheus, InfluxDB, Datadog.
  • scenario/executor modelconstant-vus, ramping-arrival-rate, per-vu-iterations and friends are expressive.
  • Extensible — xk6 adds modules for SQL, Kafka, Redis, etc.

Base script (we'll compare against it in section 4):

// k6 script: login + ramp 50 → 200 RPS for 5min
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  scenarios: {
    login_ramp: {
      executor: 'ramping-arrival-rate',
      startRate: 50,
      timeUnit: '1s',
      preAllocatedVUs: 50,
      maxVUs: 500,
      stages: [
        { target: 50, duration: '1m' },
        { target: 200, duration: '5m' },
        { target: 200, duration: '2m' },
      ],
    },
  },
  thresholds: {
    http_req_duration: ['p(99)<500'],
    http_req_failed: ['rate<0.01'],
  },
};

export default function () {
  const res = http.post('https://api.example.com/login', JSON.stringify({
    user: 'demo',
    pass: 'pw'
  }), { headers: { 'Content-Type': 'application/json' } });
  check(res, { 'status 200': (r) => r.status === 200 });
  sleep(1);
}

Grafana Cloud k6 pricing sense (2026): free tier offers ~50 VUh/month; Pro plans start around $299/month with more VUh and concurrency. Distributed and regional runs are the convenience play; the alternative is self-hosted distributed (multiple nodes running the same script, results aggregated).

Limits:

  • Distributed runs need setup in OSS — the grafana/k6-operator for Kubernetes exists, but it's operational overhead.
  • The JS runtime is Goja (an ES5+ embedded in Go), not V8. Some modern JS features need babel transforms.
  • Heavy data manipulation is safer outside the scenario.

4. Same scenario, different tools — POST /login + ramp 50 → 200 RPS

Side-by-side: k6 / Locust / Vegeta for the same shape.

k6

The script in section 3. The key bits: the ramping-arrival-rate executor and thresholds for p99 and error rate as code.

Locust (Python)

# locustfile.py
from locust import HttpUser, task, LoadTestShape, constant_throughput

class LoginUser(HttpUser):
    wait_time = constant_throughput(1)  # 1 req/sec per user

    @task
    def login(self):
        self.client.post(
            "/login",
            json={"user": "demo", "pass": "pw"},
            headers={"Content-Type": "application/json"},
        )

class RampShape(LoadTestShape):
    stages = [
        {"duration": 60, "users": 50, "spawn_rate": 50},
        {"duration": 360, "users": 200, "spawn_rate": 5},
        {"duration": 480, "users": 200, "spawn_rate": 0},
    ]

    def tick(self):
        run_time = self.get_run_time()
        for stage in self.stages:
            if run_time < stage["duration"]:
                return (stage["users"], stage["spawn_rate"])
        return None

Run: locust -f locustfile.py --headless -H https://api.example.com. Distributed via --master and --worker, with well-known Helm charts for Kubernetes.

Vegeta (CLI)

# step 1: 50 RPS for 1m
echo "POST https://api.example.com/login" | \
  vegeta attack -rate=50 -duration=60s -body=body.json \
                -header="Content-Type: application/json" \
  | vegeta report -type=hist[0,100ms,200ms,500ms,1s]

# step 2: 200 RPS for 5m
echo "POST https://api.example.com/login" | \
  vegeta attack -rate=200 -duration=5m -body=body.json \
                -header="Content-Type: application/json" \
  | tee result.bin \
  | vegeta report
vegeta plot result.bin > plot.html

Vegeta keeps scenarios deliberately simple — a fixed rate for a fixed duration. Ramps usually come from chaining commands or driving from a shell script. That simplicity is its strength — one line measures, vegeta report -type=json and vegeta plot give you the distribution and timeseries.

Side-by-side observations:

  • Expressiveness: Locust (most freedom) ≈ k6 > Vegeta. Vegeta is simple on purpose.
  • CPU efficiency: k6 > Vegeta > Locust (single-worker; Locust compensates via distributed).
  • CI friendliness: k6 (threshold exit codes) ≈ Vegeta (grep reports). Locust runs headless in CI too.
  • Result visualization: k6 (Cloud k6 or own Prometheus) > Locust (web UI) > Vegeta (plot HTML).

5. Locust — the comfortable friend for Python teams

Status (2026): actively maintained, v2.x stable. Locust's strength is behavior modeling in code — represent what users do as classes/methods with @task weights.

When it fits:

  • Python-friendly team that wants to call data and abstraction libraries directly.
  • Complex user behavior (multi-page flows, stateful sessions).
  • Distributed runs needed but no SaaS — --master/--worker is genuinely simple.

Limits:

  • Single-worker throughput is lower than k6. Python's gevent concurrency is fine, but Go is lighter.
  • The built-in web UI is nice but doesn't match a k6 + Grafana stack.

Tip: Locust's killer feature is distributed is easy. If you need 100k+ RPS, spinning up dozens of workers feels natural. Deploy via Helm to Kubernetes, scrape metrics into Prometheus — the pattern is familiar and operationally light.


6. Vegeta — the elegance of one line

Status (2026): maintained by a small set of contributors, stable and simple. New features are rare, and that's the point.

Why Vegeta survives:

  • One-line measurementecho "GET https://..." | vegeta attack -rate=100 -duration=30s | vegeta report. What takes a file and a runner and a container mount with other tools is a single line here.
  • Accurate distribution analysisvegeta report shows p50/p90/p95/p99/min/mean/max in one go. Histogram buckets are CLI flags.
  • Result serialization — the .bin format saves results for later reprocessing. CI can archive the bin and analyze it later.

Limits:

  • Scenario expressiveness is minimal — a fixed rate or a chained set of steps. Not for complex user simulations.
  • Distributed is "run the same command on multiple machines and merge bins" — manual.

Typical use: precisely measuring one hot path's latency distribution, micro-bench regression in CI, "is the server alive right now" quick check.


7. Gatling — the JVM heavyweight

Status (2026): Gatling 3.x stable. Both Gatling Enterprise (paid, formerly FrontLine) and OSS are active. Scala DSL is the default; Java and Kotlin DSLs are first-class citizens now.

Why it's still picked:

  • DSL expressiveness — scenarios, chaining, assertions feel natural as code.
  • Reporting — clean HTML reports out of the box; Enterprise adds distributed and team workflows.
  • JVM-friendly orgs — fits Maven/Gradle builds naturally.
  • Scala barrier dropped — Java DSL is a first-class citizen.

When it fits:

  • JVM-based backends, want integration with the existing build system.
  • Complex scenarios you want to keep in code, code-reviewed.
  • Need enterprise support.

Limits:

  • Not for lightweight one-liners — JVM startup and SBT/Maven cost.
  • Scala barrier is lower but not zero.

8. Artillery — YAML scenarios, fast start

Status (2026): OSS + Cloud (paid). The appeal is YAML scenarios. v2 strengthened distributed runs via Cloud.

Why it's picked:

  • Declarative YAML — describe URL/payload/flow without writing code.
  • Node.js-based — familiar to Node teams.
  • Quick startnpm install -g artillery and a yml file is enough to run.

Limits:

  • Single-node throughput is below k6 (Node event-loop limits).
  • Very high load needs Cloud or multiple instances.

Example (slightly different shape):

config:
  target: 'https://api.example.com'
  phases:
    - duration: 60
      arrivalRate: 50
    - duration: 300
      arrivalRate: 50
      rampTo: 200
    - duration: 120
      arrivalRate: 200
scenarios:
  - flow:
      - post:
          url: '/login'
          json:
            user: 'demo'
            pass: 'pw'
          expect:
            - statusCode: 200

9. JMeter — the old guard

Status (2026): Apache JMeter 5.x maintained. Largest body of learning material, widest plugin ecosystem. GUI-centric but headless runs are officially supported.

Why it still appears:

  • Legacy assets — many orgs own piles of .jmx files. Migration cost vs. maintenance cost.
  • Plugins — Prometheus listener, custom protocols, BlazeMeter integration.
  • Finance, telecom, regulated — internal standards stuck on JMeter.
  • GUI-friendly — QA teams that don't write code can drive it (both blessing and curse).

Why new teams rarely choose it fresh:

  • XML (.jmx) scenarios — not git-diff-friendly.
  • Modern UX/CLI friendliness lags.
  • CI is possible but heavier than k6/Locust.

Guidance: there's almost no reason a new project would pick JMeter fresh. But if you have the assets, the cost of throwing them away vs. keeping them is a separate decision. The common pattern is "write new tests in k6/Gatling, keep the old in JMeter, migrate as opportunity allows."


10. Micro-benchmarks — wrk / wrk2 / autocannon / Bombardier

These four are specialized for "peak throughput and latency distribution of one endpoint, fast."

wrk

  • Written in C, very fast. Lua scripting for light customization.
  • HTTP only, keep-alive friendly.
  • Caveat: no rate-limit — always at max load. Use for measuring the ceiling.

wrk2

  • A fork of wrk that supports fixed-rate runs — "exactly 1000 RPS for 30 seconds."
  • Best fit for micro-bench + fixed-rate measurement.
  • Stronger on coordinated-omission correction.

autocannon

  • Node.js-based. npm install -g autocannon, then autocannon -c 50 -d 30 https://....
  • Suits Node teams wanting fast CI benches.

Bombardier

  • Single Go binary. Dead simple and fast. bombardier -c 125 -n 1000000 https://....
  • Almost no scenario expression — that's the point.
  • Maintenance is alive but mostly in stability mode.

When which:

  • Need precise latency distribution and fixed rate → wrk2.
  • Just want to throw load quickly → wrk or Bombardier.
  • Node team in CI → autocannon.
  • Need even a small scenario → not these four; reach for Vegeta or k6.

11. Non-HTTP protocols — gRPC, WebSocket, real browser

In 2026 load testing isn't just HTTP. gRPC, WebSocket, and headless real browsers are all valid targets.

gRPC

  • ghz — a CLI for gRPC only. ghz --insecure --proto ./svc.proto --call svc.Hello -c 50 -n 10000 .... Simple and precise.
  • k6 gRPC moduleimport grpc from 'k6/net/grpc' mixes gRPC calls into a scenario.
  • fortio — born inside Istio. Both HTTP and gRPC, strong on p50–p999 distribution analysis.

WebSocket

  • k6 WS moduleimport ws from 'k6/ws'. Connection count, message RPS, session length scenarios all expressible.
  • Artillery — first-class WebSocket support in YAML.
  • Gatling — strong WebSocket scenario expressiveness.

Real browser load

  • k6 browser module — Playwright backend. Runs JS, renders, interacts in a real browser. Use cases: frontend regression, page-load SLOs.
  • Cost warning: browser instances are heavy; think in concurrent sessions, not RPS.

12. What "a good load test" means — 2026 checklist

Even with a good tool, a bad scenario gives bad results. The core of a good load test.

1) Production-like data

  • User IDs, payload sizes, token distribution should look like production.
  • "One user hitting the same page 10k times" all fits in cache — production doesn't.
  • A common pattern: sample payloads from production, anonymize, replay.

2) Distribution, not a flat rate

  • "Constant 1000 RPS" is fine for measurement but far from reality.
  • Production has bursts, dips, diurnal cycles.
  • Model with k6's ramping-arrival-rate, Locust's LoadTestShape.

3) Warm-up and ramp-up

  • Caches, DB connection pools, JIT all start cold — measuring during cold start gives pessimistic numbers.
  • Set aside the first 1–2 minutes as warm-up, exclude from measurement.

4) p99 (not the average)

  • "Average latency" is not your SLO's friend — it hides the long tail.
  • p95, p99, p999 (especially p99) connect to SLOs. Check percentiles in every tool's output.
  • A tool can under-report p99 due to coordinated omission — wrk2 was the first to popularize the fix.

5) Separate error rates

  • Computing latency only over successful responses hides dead requests.
  • Count 4xx, 5xx, timeouts, connection refused separately, with thresholds.

6) Multiple measurement points

  • Client-side latency from the load tool plus server-side RED (Rate, Error, Duration) plus downstream dependencies.
  • Load tool says slow, server says fast → network or measurement issue. Vice versa exists too.

7) Regular, not one-shot

  • Not a single pre-launch run; a weekly/monthly regression suite.
  • Track how code changes shift latency distributions over time.

13. Self-host vs cloud — cost and operations

Once distributed is needed, two paths.

Self-host distributed

  • k6 OSS + grafana/k6-operator (k8s) — pods run the test, results land in Prometheus/InfluxDB.
  • Locust master/worker — simplest. Helm chart with N workers.
  • Same command on N nodes + merge results — vegeta/wrk/Bombardier style.

Pros: cost control, data stays in-house. Cons: operational overhead, regional distribution is hard.

Cloud

  • Grafana Cloud k6 — distributed runs, regions, dashboards. From around $299/month.
  • BlazeMeter — JMeter/Gatling/k6 compatible enterprise SaaS.
  • Artillery Cloud — Artillery-based SaaS.
  • Loader.io, k6 Cloud free tier — small free tiers for occasional measurement.

Pros: regions, instant runs, instant dashboards. Cons: cost adds up (a weekly large test can quickly hit hundreds to thousands per month).

Rule of thumb: one-off big runs (pre-launch) — cloud is cheap and fast. Regular regression — self-host is cheaper long-term. Many orgs mix — daily CI self-hosted, quarterly big run on cloud.


14. Decision frame — picking honestly

SituationPick
Starting fresh, generic backendk6
Python team, complex behaviorLocust
One-line micro-benchVegeta or wrk2
Node team, fast CIArtillery or autocannon
Enterprise JVM orgGatling
Legacy JMeter assetsKeep JMeter + add k6 for new
gRPCghz or k6 gRPC
Browser loadk6 browser
Pure throughput ceilingwrk or Bombardier
Chaos + loadk6/Locust + Toxiproxy/Litmus

Mixing is common. Within one org: Vegeta for micro-bench, k6 for general load, JMeter for the big legacy scenario. That's the real picture. Don't force a single tool — accepting the right tool per area keeps operations simpler.


15. Anti-patterns and traps

  • Running directly against production — use staging or an isolated production-like environment. Production canaries are a different technique.
  • Bypassing DNS/CDN to hit origin directly — measurement passes; SLOs include CDN. The measurement path must match the user path.
  • Measuring on localhost and concluding — network latency is 0, RPS-only views give false confidence.
  • Constant rate, single pass, declare success — production is a distribution.
  • Looking only at average latency — look at p99.
  • Looking only at the load tool — pair with server metrics.
  • One-off pre-launch run — put it in regression.
  • Measuring scenarios with wrk — wrong tool.
  • Trying 100k RPS from a single node — confusing tool limits with system limits.

Epilogue — measurement is a decision tool

The tools are abundant. JMeter's monolith era is gone; k6 has become the default. Locust is the friendly Python option, Vegeta the elegant one-liner, Gatling the JVM heavyweight, Artillery the quick starter, and wrk/wrk2/autocannon/Bombardier are the micro-bench specialists.

But tools don't make the result. Does the scenario resemble production? Did you look at percentiles? Did you warm up? Is it regression? Those make the result. The work after picking a tool is longer and more important.

One-line summary: "It runs fine" is not measurement. p99, distribution, scenario — those are measurement. Tools are how you get there; the destination is something you have to define.

12-item checklist

  1. Is the purpose clear (micro/load/stress/spike)?
  2. Is the data production-like?
  3. Is the rate a distribution/ramp, not a flat constant?
  4. Did you exclude warm-up from measurement?
  5. Is p99 (or p999) tied to your SLO?
  6. Are error rates separated from latency?
  7. Are client and server metrics looked at together?
  8. Is regression wired into CI?
  9. Did you make a self-host vs cloud decision for distributed?
  10. If non-HTTP, are you using the right tool (gRPC/WS/browser)?
  11. Does the measurement path match the user path (DNS, CDN)?
  12. Do you understand coordinated-omission correction?

Ten anti-patterns

  1. Only looking at the average — look at p99.
  2. One flat-rate run as "passed" — model the distribution.
  3. Measuring on localhost and concluding — no network.
  4. Loading production directly — use staging.
  5. Looking only at the tool — look at server metrics too.
  6. One-shot pre-launch — make it regression.
  7. Doing everything in JMeter — pick per area.
  8. Forcing 100k RPS from one node — tool limit ≠ system limit.
  9. Ignoring warm-up — early data poisons the conclusion.
  10. Dropping error counts — dead requests hide.

Next post teasers

Candidates: production signal vs noise — designing RED/USE/SLO dashboards, chaos engineering 2026 — Litmus, Chaos Mesh, Gremlin, AWS FIS, performance regression CI — from a one-liner to a distribution.

"What can be measured can be improved. And if you don't look at the distribution, you aren't measuring."

— Load/performance testing tools 2026, end.


References