Skip to content

JMeter WebSocket Load Testing

Load test WebSocket APIs with JMeter plugins: install options, open/message/close flows, auth tickets, CLI runs, and injector sizing for long-lived sockets.

Difficulty
advanced
Guide type
how-to
Estimated read time
11 min read
Last verified version
Verified JMeter 5.6

Apache JMeter’s core distribution focuses on protocols such as HTTP, JDBC, JMS, LDAP, and FTP (see the component reference sampler list). WebSocket is not a built-in core sampler in the same way HTTP Request is. Production WebSocket load tests with JMeter almost always depend on the plugin ecosystem (JMeter Plugins / Plugins Manager and community WebSocket plugins). This guide explains a grounded, plugin-aware workflow: install plugins, design sessions, correlate, size threads, and operate CLI load without overstating what core JMeter alone can do.

A WebSocket client:

  1. Completes an HTTP Upgrade handshake.
  2. Keeps a long-lived bidirectional connection.
  3. Sends and receives messages (text/binary) with app-level framing.
  4. Closes or drops under errors.

Load dimensions differ from REST:

DimensionREST-style HTTPWebSocket
ConnectionOften short (keep-alive pool)Long-lived per VU
Metric focusRequest latency, RPSConnect time, message latency, msg/s, errors, connection drops
Thread usageSample ≈ requestThread may block on read/write for the session lifetime
MemoryPer-sample buffersPer-open connection state

JMeter’s thread model (best practices on sizing threads) still applies: each concurrent session typically needs a thread (or plugin-specific async mode if offered). Undersizing threads relative to message rates invites coordinated omission style bias.

Core JMeter does not install third-party plugins by itself. Community practice:

  1. Install JMeter Plugins Manager (see plugins essentials and the JMeter wiki plugins page linked from project docs such as Boss).
  2. Search for a maintained WebSocket plugin compatible with your JMeter major version.
  3. Install, restart JMeter, confirm new samplers appear under Sampler.
  4. For CI/Docker, bake the same plugin set into the image or install in the job before jmeter -n.

Distributed testing requires identical plugins on every worker. Missing plugin JARs cause serialization or class-not-found failures remotely.

Test Plan
├── HTTP Request Defaults / Header Manager (auth bootstrap)
├── CSV Data Set (users)
└── Thread Group
├── HTTP Login (core) + extract token
├── WebSocket Open (plugin) // pass token via query/header if supported
├── Loop Controller
│ ├── WebSocket Write/Ping (plugin)
│ ├── WebSocket Read (plugin) + assertions/extractors if available
│ └── Timer (pace messages)
└── WebSocket Close (plugin)

Exact sampler names depend on the plugin (Open, Single Read, Single Write, request-response, ping/pong, etc.).

PatternApproach
Ticket in query stringExtract from HTTP, use \${ticket} in open URL
Bearer on upgradePlugin header fields if supported; else query ticket
Cookie sessionCookie Manager + open to same host
SubprotocolPlugin field for Sec-WebSocket-Protocol when required

Use JWT/OAuth guidance for the HTTP side. Never hard-code long-lived tokens in the plan.

  1. Define message rate per session (e.g. 1 msg/s) and session count (threads).
  2. Aggregate throughput ≈ sessions × msg/s if the server keeps up.
  3. Use timers for pacing; avoid unbounded tight write loops unless stress-testing.
  4. Separate samplers for connect, write, read, close so the dashboard shows which phase fails.
  5. Assert on payload fragments or status where the plugin exposes response data.

Payloads: prefer variables and CSV over huge embedded binaries. Functions such as \${__UUID} and \${__time} help unique message ids (functions).

If the server pushes an id you must echo:

  1. Read sampler captures response.
  2. Regex/JSON extractor (if response is available as sample data) sets \${msgId}.
  3. Next write uses \${msgId}.

If the plugin does not expose body to standard post-processors, check plugin-specific “read to variable” options in its documentation.

Same lean rules as HTTP (best practices):

Terminal window
jmeter -n -t websocket-plan.jmx -l results.jtl -e -o report/ \
-Jthreads=200 -Jrampup=120 -Jhost=ws.example.com
  • Disable View Results Tree for load.
  • Size heap for concurrent connections (Heap Estimator).
  • Watch injector file descriptors and ephemeral ports; long-lived sockets stress OS limits.
  • Prefer dedicated injectors; do not co-locate with the system under test.

From JMeter results (labels you control) plus optional Backend Listener:

  • Connect success rate and connect time
  • Write/read error %
  • Response time for request-response message pairs
  • Active threads / open sessions
  • Server-side connection count and message lag (not only JMeter)

HTML dashboard still works on the JTL if samples are recorded as standard SampleResults.

  1. Core JMeter alone is not a full WebSocket IDE.
  2. Plugin quality and maintenance vary; pin versions.
  3. Browser WebSocket traffic recorded via HTTP proxy may not capture socket frames the way HTTP is recorded.
  4. Extremely high fan-in may need specialized tools; prove scale with pilots.
  5. TLS (wss://) needs correct JVM trust stores, same as HTTPS.
SymptomChecks
Sampler missing in GUIPlugin not installed / wrong JMeter version
Works in GUI, fails in CIPlugin absent in CI image
401 on openToken query/header not correlated
Handshake failProxy, TLS, wrong scheme ws vs wss
Threads stuckBlocking read without timeout; plugin timeout settings
OOMToo many open sessions per JVM; raise heap or split engines

Does stock Apache JMeter include a WebSocket sampler?

Section titled “Does stock Apache JMeter include a WebSocket sampler?”

WebSocket support is provided through the plugin ecosystem, not as a primary core sampler like HTTP Request. Install a maintained WebSocket plugin via Plugins Manager or manual JARs.

Can I use the HTTP(S) Test Script Recorder for WebSockets?

Section titled “Can I use the HTTP(S) Test Script Recorder for WebSockets?”

The recorder is built for HTTP(S) request/response capture. Do not expect full WebSocket frame recording the way you record REST calls. Build socket steps with the plugin after HTTP login.

How many threads do I need for WebSocket tests?

Section titled “How many threads do I need for WebSocket tests?”

Often one thread per concurrent connection for classic Thread Groups. Size from concurrent sessions and message pacing, then validate injector CPU, RAM, and file descriptors.

Do plugins need to be on every distributed worker?

Section titled “Do plugins need to be on every distributed worker?”

Yes. Workers must match the controller’s JMeter version and plugin set, same as other third-party engines in remote testing.

Should I still generate an HTML dashboard?

Section titled “Should I still generate an HTML dashboard?”

Yes. If the plugin writes standard sample results, -e -o report/ works. Label connect/write/read/close clearly for readable statistics.

On this page