TL;DR: Apache JMeter is the world’s most popular open-source load testing tool. Install it, create a Thread Group, add HTTP Samplers, run in CLI mode, and analyze results in the HTML report. Use distributed mode to scale beyond 5,000 users.

Apache JMeter is the most downloaded load testing tool globally, with over 10 million downloads according to the Apache Software Foundation. According to the 2024 SmartBear State of API Testing report, 47% of teams conducting load testing use JMeter — more than twice the adoption of the next most popular tool. JMeter’s GUI enables test creation through recording or manual configuration without programming knowledge. Advanced usage adds parameterization via CSV Data Set Config, correlation via Regular Expression Extractor, and CI/CD integration through non-GUI mode execution. This tutorial covers JMeter from first test to CI/CD pipeline integration: test plan structure, thread groups, samplers, assertions, parameterization, and distributed testing.

What is Apache JMeter?

JMeter is an open-source load testing tool written in Java. It simulates multiple users sending requests to measure how systems perform under load.

What JMeter can test:

  • Web applications (HTTP/HTTPS)
  • REST and SOAP APIs
  • Databases (JDBC)
  • FTP servers
  • Message queues (JMS)
  • Mail servers (SMTP, POP3)

Why JMeter:

  • Free and open-source — no licensing costs
  • GUI for test design — visual test creation
  • Protocol support — HTTP, JDBC, JMS, FTP, and more
  • Extensible — plugins for additional features
  • Distributed testing — scale across machines
  • CI/CD integration — command-line execution

Installation

Prerequisites

JMeter requires Java 8 or higher.

# Check Java version
java -version

# If not installed, install OpenJDK
# macOS
brew install openjdk

# Ubuntu/Debian
sudo apt install openjdk-11-jdk

# Windows - download from adoptium.net

Installing JMeter

# Download latest version (5.6.3 as of 2026)
wget https://dlcdn.apache.org/jmeter/binaries/apache-jmeter-5.6.3.tgz

# Extract
tar -xzf apache-jmeter-5.6.3.tgz

# Run JMeter GUI
cd apache-jmeter-5.6.3/bin
./jmeter.sh    # Linux/macOS
jmeter.bat     # Windows

JMeter Concepts

Test Plan Hierarchy

Test Plan
├── Thread Group (Users)
│   ├── Sampler (HTTP Request)
│   │   ├── Config Element (Headers, Cookies)
│   │   ├── Pre-Processor (Modify before send)
│   │   └── Post-Processor (Extract from response)
│   ├── Assertion (Verify response)
│   └── Timer (Delay between requests)
├── Listener (View results)
└── Config Element (Global settings)

Key Components

Thread Group — Simulates users

Number of Threads: 100        # Concurrent users
Ramp-Up Period: 60 seconds    # Time to start all users
Loop Count: 10                # Iterations per user

Sampler — Sends requests (HTTP, JDBC, etc.)

Listener — Collects and displays results

Assertion — Validates responses

Timer — Adds delays between requests

Creating Your First Test

Step 1: Create Test Plan

  1. Open JMeter
  2. Right-click Test Plan → Add → Threads → Thread Group
  3. Configure Thread Group:
    • Number of Threads: 10
    • Ramp-Up Period: 10
    • Loop Count: 5

Step 2: Add HTTP Request

  1. Right-click Thread Group → Add → Sampler → HTTP Request
  2. Configure:
    • Protocol: https
    • Server Name: jsonplaceholder.typicode.com
    • Path: /posts/1
    • Method: GET

Step 3: Add Listeners

  1. Right-click Thread Group → Add → Listener → View Results Tree
  2. Add → Listener → Summary Report
  3. Add → Listener → Response Time Graph

Step 4: Run Test

  1. Click the green Start button
  2. View results in listeners
  3. Save test plan (.jmx file)

HTTP Request Configuration

GET Request with Parameters

Server Name: api.example.com
Path: /users
Method: GET

Parameters:
Name        | Value
------------|-------
page        | 1
limit       | 20
sort        | name

POST Request with JSON Body

Server Name: api.example.com
Path: /users
Method: POST

Body Data:
{
  "name": "John Doe",
  "email": "john@example.com",
  "role": "user"
}

HTTP Header Manager:
Content-Type: application/json

Headers Configuration

Right-click HTTP Request → Add → Config Element → HTTP Header Manager

Header Name          | Value
---------------------|---------------------------
Content-Type         | application/json
Authorization        | Bearer ${token}
Accept               | application/json
X-Request-ID         | ${__UUID()}

Variables and Parameterization

User Defined Variables

Right-click Test Plan → Add → Config Element → User Defined Variables

Name        | Value
------------|---------------------------
base_url    | https://api.example.com
api_version | v2
timeout     | 30000

Use in requests: ${base_url}/${api_version}/users

CSV Data Set Config

For data-driven testing with multiple users.

Create users.csv:

username,password,expected_name
user1,pass1,John Doe
user2,pass2,Jane Smith
user3,pass3,Bob Wilson

Add CSV Data Set Config:

Filename: users.csv
Variable Names: username,password,expected_name
Delimiter: ,
Recycle on EOF: True
Stop thread on EOF: False

Use variables: ${username}, ${password}

Extracting Values from Responses

JSON Extractor (for JSON responses):

Right-click HTTP Request → Add → Post Processors → JSON Extractor

Variable Name: userId
JSON Path Expression: $.data.id
Match No: 1
Default Value: NOT_FOUND

Regular Expression Extractor (for any text):

Reference Name: token
Regular Expression: "access_token":"(.+?)"
Template: $1$
Match No: 1

Assertions

Response Assertion

Verify response contains expected text.

Apply to: Main sample only
Field to Test: Response Body
Pattern Matching Rules: Contains
Patterns to Test: "success": true

JSON Assertion

Validate JSON structure and values.

Assert JSON Path exists: $.data.id
Expected Value: 123
Match as regular expression: false

Duration Assertion

Fail if response takes too long.

Duration in milliseconds: 2000

Response Code Assertion

Check HTTP status code.

Response Code: 200
Pattern Matching Rules: Equals

Timers

Constant Timer

Fixed delay between requests.

Thread Delay: 1000 milliseconds

Gaussian Random Timer

Realistic delays with randomization.

Deviation: 500 milliseconds
Constant Delay Offset: 1000 milliseconds
# Results in delays between 500-1500ms

Constant Throughput Timer

Control requests per minute.

Target throughput: 60.0 per minute
Calculate based on: All active threads

Test Scenarios

Load Test

Simulate expected production load.

Thread Group:
- Threads: 100
- Ramp-Up: 300 seconds (5 minutes)
- Duration: 1800 seconds (30 minutes)
- Loop Count: Forever (checked)

Goal: Verify system handles normal traffic

Stress Test

Find breaking point.

Thread Group 1: 100 users, 60s ramp
Thread Group 2: 200 users, 60s ramp (starts after TG1)
Thread Group 3: 500 users, 60s ramp (starts after TG2)
Thread Group 4: 1000 users, 60s ramp (starts after TG3)

Goal: Find when system degrades/fails

Spike Test

Sudden traffic surge.

Thread Group:
- Threads: 1000
- Ramp-Up: 10 seconds (fast spike)
- Duration: 120 seconds
- Loop Count: Forever

Goal: Test system recovery from sudden load

Endurance Test

Long-running stability test.

Thread Group:
- Threads: 50
- Ramp-Up: 60 seconds
- Duration: 28800 seconds (8 hours)
- Loop Count: Forever

Goal: Find memory leaks, resource exhaustion

Running Tests in CLI Mode

GUI mode is for test design only. Always run actual tests in CLI mode.

# Basic CLI execution
jmeter -n -t test_plan.jmx -l results.jtl

# With HTML report
jmeter -n -t test_plan.jmx -l results.jtl -e -o report_folder

# With properties
jmeter -n -t test_plan.jmx -l results.jtl \
  -Jusers=100 \
  -Jrampup=60 \
  -Jduration=300

CLI Parameters

ParameterDescription
-nNon-GUI mode
-tTest plan file
-lResults file
-eGenerate HTML report
-oOutput folder for report
-JDefine property
-GDefine global property

Distributed Testing

For high load, distribute tests across multiple machines.

Architecture

┌─────────────────┐
│   Controller    │
│   (Master)      │
└────────┬────────┘
         │
    ┌────┴────┐
    │         │
┌───▼───┐ ┌───▼───┐
│Worker1│ │Worker2│
│(Slave)│ │(Slave)│
└───────┘ └───────┘

Setup Workers

On each worker machine:

# Start JMeter server
cd apache-jmeter-5.6.3/bin
./jmeter-server

Configure Controller

Edit jmeter.properties:

remote_hosts=worker1:1099,worker2:1099,worker3:1099

Run Distributed Test

# Run on all remote hosts
jmeter -n -t test.jmx -r -l results.jtl

# Run on specific hosts
jmeter -n -t test.jmx -R worker1,worker2 -l results.jtl

Analyzing Results

Key Metrics

MetricDescriptionTarget
ThroughputRequests/secondHigher is better
Response TimeTime to complete requestLower is better
Error RatePercentage of failures< 1%
90th Percentile90% of requests faster than< SLA

Summary Report

Label    | # Samples | Average | Min | Max  | Error% | Throughput
---------|-----------|---------|-----|------|--------|------------
Homepage | 1000      | 245     | 120 | 1250 | 0.00%  | 45.2/sec
Login    | 1000      | 890     | 450 | 3200 | 0.10%  | 12.1/sec
Search   | 1000      | 1250    | 600 | 5000 | 2.50%  | 8.3/sec

HTML Report

Generated with -e -o flags:

  • Dashboard with summary
  • Response time graphs
  • Throughput over time
  • Error analysis
  • Top 5 errors

AI-Assisted JMeter Testing

AI tools can help create and optimize JMeter tests.

What AI does well:

  • Generate test plans from API documentation
  • Create realistic test data
  • Suggest assertion patterns
  • Explain performance metrics

What still needs humans:

  • Understanding system architecture
  • Setting realistic load targets
  • Interpreting results in context
  • Deciding on acceptable thresholds

Useful prompt:

Generate a JMeter test plan XML for load testing a REST API with endpoints: GET /users, POST /users, GET /users/{id}. Include authentication header, response assertions, and throughput timer for 100 requests per minute.

FAQ

What is Apache JMeter?

Apache JMeter is a free, open-source load testing tool written in Java that simulates concurrent users to measure application performance under load.

Apache JMeter is a free, open-source load testing tool written in Java. It simulates multiple concurrent users sending requests to web applications, APIs, or databases to measure performance under load. JMeter supports HTTP, HTTPS, JDBC, JMS, FTP, and other protocols. It’s used to find performance bottlenecks before production deployment.

Is JMeter free to use?

Yes — JMeter is 100% free under Apache License 2.0, with no paid tiers or feature restrictions.

Yes, JMeter is 100% free and open-source under Apache License 2.0. There are no paid tiers, enterprise editions, or feature restrictions. All functionality including distributed testing, plugins, and reporting is available to everyone at no cost.

How many users can JMeter simulate?

A single JMeter instance handles 1,000–5,000 concurrent users; distributed mode scales to millions.

A single JMeter instance typically simulates 1,000-5,000 concurrent users depending on hardware resources and test complexity. For higher loads, JMeter supports distributed testing across multiple machines, enabling simulation of hundreds of thousands or millions of virtual users by adding more worker nodes.

JMeter vs Gatling — which is better?

Choose JMeter for GUI-based ease and broad community support; choose Gatling for code-as-tests and high-scale CI/CD integration.

JMeter offers an easier GUI-based approach and larger community support, making it ideal for beginners and quick tests. Gatling provides better performance, code-as-tests approach, and cleaner reports, better suited for CI/CD pipelines. Choose JMeter for accessibility; Gatling for high-scale automated testing.

Should I use JMeter GUI or CLI mode?

Use GUI mode for design only; always run load tests in CLI mode to avoid memory overhead and result distortion.

Use GUI mode only for designing and debugging test plans. When you run actual load tests, always switch to CLI mode with jmeter -n -t test.jmx -l results.jtl. GUI mode consumes significant memory for rendering results in real-time, which distorts test outcomes and limits the number of threads you can simulate. CLI mode uses 30-50% less memory and produces more accurate results.

How do I integrate JMeter with CI/CD?

Run jmeter -n -t test.jmx -l results.jtl -e -o report in your pipeline and use the Performance Plugin for Jenkins or upload the HTML report as a GitHub Actions artifact.

Run JMeter in CLI mode within your pipeline: jmeter -n -t test.jmx -l results.jtl -e -o report. For Jenkins, use the Performance Plugin to parse JTL files and track trends. For GitHub Actions, run JMeter as a step and upload the HTML report as an artifact. Set pass/fail thresholds on error rate and response time to automatically gate deployments.

“JMeter tests are conversations with your system under stress. The Thread Group sets the pace, the Samplers ask the questions, and the Listeners tell you how the system answered. Master those three elements and you can test any system that communicates over a network.” — Yuri Kan, Senior QA Lead

See Also