Documentation for automated readers
A curated documentation index is available at: https://grafana.com/llms.txt
A complete documentation index is available at: https://grafana.com/llms-full.txt
These indexes can help with page discovery before fetching individual documents.
This page is also available in Markdown, which may be easier for automated readers and AI tools to parse than HTML. The Markdown version is available at https://grafana.com/docs/k6/latest/javascript-api/k6-x-tcp.md, or by sending Accept: text/markdown to https://grafana.com/docs/k6/latest/javascript-api/k6-x-tcp/. For broader documentation discovery, the curated index is available at https://grafana.com/llms.txt and the complete index is available at https://grafana.com/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

