Skip to content

k6 WebSocket Connection Timeout Fix

DodaTech Updated 2026-06-24 3 min read

In this tutorial, you'll learn about k6 websocket connection timeout fix. We cover key concepts, practical examples, and best practices.

Your k6 WebSocket connection times out — the ws.connect() call hangs and eventually fails with dial tcp: i/o timeout. The WebSocket endpoint is unreachable, the protocol is wrong, or the server does not respond to the upgrade handshake.

The Problem

import ws from 'k6/ws';

export default function () {
  const url = 'ws://api.example.com/socket';
  const response = ws.connect(url, function (socket) {
    socket.on('open', function () {
      console.log('Connected');
    });
  });
}
WARN[0010] ws.connect ws://api.example.com/socket: dial tcp: i/o timeout

The server at api.example.com does not accept WebSocket connections, or the URL uses ws:// when the server expects wss://.

Step-by-Step Fix

1. Check WebSocket URL protocol

import ws from 'k6/ws';

export default function () {
  // Use wss:// for TLS-secured WebSocket
  const url = __ENV.WS_URL || 'wss://api.example.com/socket';

  const response = ws.connect(url, function (socket) {
    socket.on('open', function () {
      console.log('Connected to ' + url);
    });

    socket.on('error', function (e) {
      console.log('WebSocket error: ' + e.error());
    });
  });
}

2. Set connection timeout

import ws from 'k6/ws';

export default function () {
  ws.connect('wss://api.example.com/socket', {
    timeout: '5s',
  }, function (socket) {
    socket.on('open', function () {
      console.log('Connected');
    });

    socket.setTimeout(function () {
      console.log('5 second timeout — closing');
      socket.close();
    }, 5000);
  });
}

3. Send and receive messages

import ws from 'k6/ws';
import { check } from 'k6';

export default function () {
  ws.connect('wss://api.example.com/chat', function (socket) {
    socket.on('open', function () {
      socket.send(JSON.stringify({ type: 'join', room: 'general' }));
    });

    socket.on('message', function (data) {
      const msg = JSON.parse(data);
      console.log(`Received: ${msg.type}`);
      socket.close();
    });

    socket.setTimeout(function () {
      socket.close();
    }, 30000);
  });
}

4. Handle WebSocket in load test scenarios

import ws from 'k6/ws';
import { check } from 'k6';

export const options = {
  vus: 10,
  duration: '30s',
  thresholds: {
    ws_connecting: ['avg<500'],
    ws_msgs_received: ['rate>0'],
  },
};

export default function () {
  ws.connect('wss://api.example.com/socket', function (socket) {
    socket.on('open', function () {
      socket.send(JSON.stringify({ action: 'ping' }));
    });

    socket.on('message', function (data) {
      const msg = JSON.parse(data);
      check(msg, {
        'received pong': (m) => m.action === 'pong',
      });
      socket.close();
    });

    socket.on('close', function () {
      console.log('Connection closed');
    });
  });
}

5. Test WebSocket with authentication

import ws from 'k6/ws';
import { check } from 'k6';

export default function () {
  const url = `wss://api.example.com/socket?token=${__ENV.WS_TOKEN}`;

  const response = ws.connect(url, {
    headers: {
      'Origin': 'https://example.com',
    },
  }, function (socket) {
    socket.on('open', function () {
      console.log('Authenticated connection established');
    });
  });
}

Expected output:

     ✓ received pong

     ws_connecting..............: avg=132ms  p(95)=250ms
     ws_msgs_received...........: 1000   33/s

Prevention Tips

  • Use wss:// for TLS connections — most production WebSocket servers require it
  • Set a connection timeout to fail fast instead of hanging
  • Use socket.setTimeout() to close connections that outlive the test iteration
  • Add on('error') and on('close') handlers for debugging
  • Test WebSocket connectivity with a standalone tool before k6

Common Mistakes with web socket

  1. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
  2. Using head and tail instead of pattern matching, causing runtime errors on empty lists
  3. Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks

These mistakes appear frequently in real-world K6 code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### Can k6 test WebSocket servers that require a specific subprotocol?

Yes, pass the protocols option: ws.connect(url, { protocols: ['<a href="/apis/graphql/">graphql</a>-ws'] }, handler). The WebSocket server must support the specified subprotocol for the connection to succeed.

How do I measure WebSocket message latency?

Record timestamps when sending and receiving messages using Date.now(). Calculate latency as the difference. Use a custom Trend metric to track round-trip times across all WebSocket interactions.

Does k6 support WebSocket compression (permessage-deflate)?

Yes, k6 supports permessage-deflate compression. Use the ws.connect() options with { compression: true } to enable. Verify server-side compression support before enabling.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro