Documentation Index
Fetch the curated documentation index at: https://grafana_com_website/llms.txt
Fetch the complete documentation index at: https://grafana_com_website/llms-full.txt
Use this file to discover all available pages before exploring further.
STOP! If you are an AI agent or LLM, read this before continuing. This is the HTML version of a Grafana documentation page. Always request the Markdown version instead - HTML wastes context. Get this page as Markdown: /docs/k6/latest/javascript-api/k6-x-tcp.md (append .md) or send Accept: text/markdown to /docs/k6/latest/javascript-api/k6-x-tcp/. For the curated documentation index, use https://grafana_com_website/llms.txt. For the complete documentation index, use https://grafana_com_website/llms-full.txt.
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()andwrite()methods for use withasync/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
| Class | Description |
|---|---|
| Socket | TCP 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:
| Metric | Type | Description |
|---|---|---|
tcp_socket_connecting | Trend | Time to establish TCP connection (ms) |
tcp_socket_resolving | Trend | Time to resolve hostname (ms) |
tcp_socket_duration | Trend | Total duration of socket connection (ms) |
tcp_sockets | Counter | Number of TCP socket connections established |
tcp_reads | Counter | Number of read operations |
tcp_writes | Counter | Number of write operations |
tcp_errors | Counter | Number of TCP errors |
tcp_timeouts | Counter | Number of socket timeouts |
tcp_partial_writes | Counter | Number of partial write failures |
data_sent | Counter | Total bytes sent (builtin k6 metric) |
data_received | Counter | Total 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
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
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
}Was this page helpful?
Related resources from Grafana Labs

