This is documentation for the next version of Grafana k6 documentation. For the latest stable release, go to the latest version.

Open source

k6/x/tcp

Note

This module is implemented as an official extension and is not part of k6 by default. However, k6’s automatic extension resolution makes it available seamlessly when you import it in your script. Refer to the extensions documentation for available extensions and details.

The k6/x/tcp module adds first-class support for raw TCP socket communication to your performance testing scripts. With this extension, you can establish TCP connections and send and receive data directly from your k6 tests.

If you’ve used Node.js’s net.Socket, the API will feel familiar, with event-driven programming, Promise-based operations, and comprehensive lifecycle management.

Key features

  • Event-driven architecture with support for socket lifecycle events (connect, data, close, error, timeout)
  • Promise-based connect() and write() methods for use with async/await
  • TLS/SSL support using standard k6 TLS configuration
  • Binary data handling: send and receive strings and ArrayBuffer
  • Automatic metrics collection for all socket operations
  • Optional custom tags for filtering and grouping metrics

Use cases

  • Load testing TCP-based services and custom binary protocols
  • Testing raw network protocol implementations under high concurrency
  • Validating server behavior and connection handling under load
  • Performance testing services that don’t use HTTP

API

ClassDescription
SocketTCP socket for connecting to servers and managing operations
Socket.connect()Establish a TCP connection
Socket.write()Send data over the socket
Socket.destroy()Close and destroy the socket
Socket.setTimeout()Set inactivity timeout
Socket.on()Register event handlers

Metrics

The extension automatically generates metrics for TCP socket operations:

MetricTypeDescription
tcp_socket_connectingTrendTime to establish TCP connection (ms)
tcp_socket_resolvingTrendTime to resolve hostname (ms)
tcp_socket_durationTrendTotal duration of socket connection (ms)
tcp_socketsCounterNumber of TCP socket connections established
tcp_readsCounterNumber of read operations
tcp_writesCounterNumber of write operations
tcp_errorsCounterNumber of TCP errors
tcp_timeoutsCounterNumber of socket timeouts
tcp_partial_writesCounterNumber of partial write failures
data_sentCounterTotal bytes sent (builtin k6 metric)
data_receivedCounterTotal bytes received (builtin k6 metric)

You can pass custom tags in the Socket constructor, connection options, or write options to attach additional metadata to each metric.

Event-driven architecture

Unlike HTTP-based tests, TCP tests use an asynchronous event loop. Each VU creates a Socket, registers event handlers, and connects to a server. The VU remains active until socket.destroy() is called or the connection is closed.

Register handlers with socket.on() before calling socket.connect(). The connect handler fires when the connection is established; the data handler fires each time data is received; the close handler fires when the connection is fully closed.

Examples

Basic usage

JavaScript
import { Socket } from "k6/x/tcp"

export default async function () {
  const socket = new Socket()

  const closed = new Promise((resolve) => {
    socket.on("close", () => {
      console.log("Connection closed")
      resolve()
    })
  })

  socket.on("error", (err) => {
    console.error("Error:", err)
  })

  const host = __ENV.TCP_HOST || "localhost"
  const port = __ENV.TCP_PORT || "8080"

  await socket.connect(port, host)
  console.log("Connected")
  socket.destroy()

  await closed
}

TLS connection

JavaScript
import { Socket } from "k6/x/tcp"

export default async function () {
  const socket = new Socket()

  const closed = new Promise((resolve) => {
    socket.on("close", resolve)
  })

  socket.on("data", (data) => {
    const response = String.fromCharCode.apply(null, new Uint8Array(data))
    console.log("Received:", response.substring(0, 100))
    socket.destroy()
  })

  socket.on("error", (err) => {
    console.error("Error:", err)
  })

  const host = __ENV.TLS_HOST || "example.com"

  await socket.connect({ port: 443, host, tls: true })
  await socket.write(`GET / HTTP/1.1\r\nHost: ${host}\r\nConnection: close\r\n\r\n`)

  await closed
}