Documentation Index Fetch the complete documentation index at: https://mintlify.com/grafana/k6-docs/llms.txt
Use this file to discover all available pages before exploring further.
k6 protocol extensions enable you to test systems using protocols beyond HTTP and WebSockets. Official protocol extensions are maintained by Grafana Labs and support automatic extension resolution.
Overview
Protocol extensions let you:
Test message brokers (MQTT, Kafka)
Load test databases (Redis, SQL)
Validate IoT infrastructure
Test event-driven architectures
Simulate thousands of protocol clients
MQTT
The k6/x/mqtt extension adds first-class support for the MQTT protocol, enabling you to test MQTT brokers and IoT infrastructure.
Key features
Event-driven architecture with lifecycle events (connect, message, end, reconnect, error)
Synchronous and asynchronous methods for all operations
Quality of Service (QoS) levels: 0, 1, and 2
Message retention and Last Will and Testament (LWT) support
Multiple broker URL schemas: mqtt://, mqtts://, ws://, wss://
SSL/TLS support with standard k6 TLS configuration
Automatic metrics collection
Basic example
import { Client } from 'k6/x/mqtt' ;
export default function () {
const client = new Client ();
client . on ( 'connect' , async () => {
console . log ( 'Connected to MQTT broker' );
client . subscribe ( 'greeting' );
client . publish ( 'greeting' , 'Hello MQTT!' );
});
client . on ( 'message' , ( topic , message ) => {
const str = String . fromCharCode . apply ( null , new Uint8Array ( message ));
console . info ( 'topic:' , topic , 'message:' , str );
client . end ();
});
client . on ( 'end' , () => {
console . log ( 'Disconnected from MQTT broker' );
});
client . connect ( __ENV [ 'MQTT_BROKER_ADDRESS' ] || 'mqtt://broker.emqx.io:1883' );
}
Async programming
Use async/await with MQTT event handlers:
import { Client } from 'k6/x/mqtt' ;
export default function () {
const client = new Client ();
client . on ( 'connect' , async () => {
console . log ( 'Connected to MQTT broker' );
await client . subscribeAsync ( 'probe' );
const intervalId = setInterval (() => {
client . publish ( 'probe' , 'ping MQTT!' );
}, 1000 );
setTimeout (() => {
clearInterval ( intervalId );
client . end ();
}, 3100 );
});
client . on ( 'message' , ( topic , message ) => {
console . info ( String . fromCharCode . apply ( null , new Uint8Array ( message )));
});
client . on ( 'end' , () => {
console . log ( 'Disconnected from MQTT broker' );
});
client . connect ( __ENV [ 'MQTT_BROKER_ADDRESS' ] || 'mqtt://broker.emqx.io:1883' );
}
QoS levels
import { Client , QoS } from 'k6/x/mqtt' ;
export default function () {
const client = new Client ();
client . on ( 'connect' , () => {
// Subscribe with QoS 1 (at least once)
client . subscribe ( 'sensor/data' , { qos: QoS . AtLeastOnce });
// Publish with QoS 2 (exactly once)
client . publish ( 'sensor/data' , 'temperature:22.5' , { qos: QoS . ExactlyOnce });
});
client . connect ( 'mqtt://localhost:1883' );
}
MQTT metrics
The extension automatically generates metrics:
mqtt_connects - Connection attempts
mqtt_connect_duration - Connection time
mqtt_publishes - Number of publish operations
mqtt_subscribes - Number of subscribe operations
mqtt_messages_received - Received messages
mqtt_messages_sent - Sent messages
Use cases
IoT load testing Simulate thousands of IoT devices publishing sensor data
Message throughput Test MQTT broker performance and message delivery rates
QoS validation Verify Quality of Service guarantees under load
Event-driven systems Test MQTT-based microservices and event architectures
Redis
The k6/x/redis extension provides a client library for interacting with Redis databases directly from k6 scripts.
Features
Load test Redis databases
Use Redis as a data store for test-script logic
Promise-based async API
Support for common Redis commands
Basic example
import redis from 'k6/x/redis' ;
export const options = {
vus: 10 ,
duration: '30s' ,
};
const client = new redis . Client ( 'redis://localhost:6379' );
export default async function () {
// Set a value
await client . set ( 'key' , 'value' );
// Get the value
const value = await client . get ( 'key' );
console . log ( 'Retrieved:' , value );
// Increment a counter
await client . incr ( 'counter' );
// Check if key exists
const exists = await client . exists ( 'key' );
console . log ( 'Key exists:' , exists );
}
Connection options
import redis from 'k6/x/redis' ;
const client = new redis . Client ({
host: 'localhost' ,
port: 6379 ,
password: 'your-password' ,
db: 0 ,
dialTimeout: '5s' ,
readTimeout: '3s' ,
writeTimeout: '3s' ,
});
Common operations
import redis from 'k6/x/redis' ;
const client = new redis . Client ( 'redis://localhost:6379' );
export default async function () {
// String operations
await client . set ( 'user:1:name' , 'Alice' );
await client . setex ( 'session:abc' , 3600 , 'session-data' ); // With expiry
const name = await client . get ( 'user:1:name' );
// Hash operations
await client . hset ( 'user:1' , 'email' , 'alice@example.com' );
await client . hset ( 'user:1' , 'age' , '30' );
const email = await client . hget ( 'user:1' , 'email' );
const user = await client . hgetall ( 'user:1' );
// List operations
await client . lpush ( 'queue:jobs' , 'job1' );
await client . rpush ( 'queue:jobs' , 'job2' );
const job = await client . lpop ( 'queue:jobs' );
// Set operations
await client . sadd ( 'users:active' , 'user1' , 'user2' , 'user3' );
const members = await client . smembers ( 'users:active' );
// Delete keys
await client . del ( 'key' );
}
Use cases
Cache load testing Test Redis cache performance under high load
Session storage Validate session management at scale
Test data sharing Share data between VUs using Redis
Rate limiting Test rate limiting implementations
SQL
The k6/x/sql extension enables testing of SQL databases including PostgreSQL, MySQL, SQLite, and more.
Supported databases
PostgreSQL
MySQL / MariaDB
Microsoft SQL Server
SQLite
ClickHouse
Basic example
import sql from 'k6/x/sql' ;
const db = sql . open ( 'postgres' , 'postgres://user:password@localhost:5432/testdb?sslmode=disable' );
export default function () {
// Execute a query
const results = sql . query ( db , 'SELECT * FROM users WHERE active = $1' , true );
console . log ( `Found ${ results . length } active users` );
// Insert data
sql . exec ( db , 'INSERT INTO users (name, email) VALUES ($1, $2)' , 'Alice' , 'alice@example.com' );
// Execute with multiple rows
for ( let i = 0 ; i < 10 ; i ++ ) {
sql . exec ( db , 'INSERT INTO logs (message) VALUES ($1)' , `Log entry ${ i } ` );
}
}
export function teardown () {
db . close ();
}
Connection strings
PostgreSQL
MySQL
SQLite
SQL Server
const db = sql . open ( 'postgres' , 'postgres://user:password@localhost:5432/database?sslmode=disable' );
Transaction example
import sql from 'k6/x/sql' ;
const db = sql . open ( 'postgres' , 'postgres://localhost:5432/testdb' );
export default function () {
// Begin transaction
const tx = db . begin ();
try {
// Execute queries in transaction
tx . exec ( 'UPDATE accounts SET balance = balance - 100 WHERE id = 1' );
tx . exec ( 'UPDATE accounts SET balance = balance + 100 WHERE id = 2' );
// Commit transaction
tx . commit ();
} catch ( error ) {
// Rollback on error
tx . rollback ();
console . error ( 'Transaction failed:' , error );
}
}
Use cases
Database load testing Test database performance under concurrent queries
Connection pooling Validate connection pool behavior
Transaction testing Test transaction isolation and deadlocks
Query performance Measure query execution times at scale
Using protocol extensions
All official protocol extensions support automatic resolution:
import mqtt from 'k6/x/mqtt' ;
import redis from 'k6/x/redis' ;
import sql from 'k6/x/sql' ;
// Use extensions directly - k6 loads them automatically
Run your test:
Build custom binary
To bundle protocol extensions in a custom binary:
xk6 build \
--with github.com/grafana/xk6-sql@latest \
--with github.com/grafana/xk6-output-prometheus-remote
Combining protocols
Test complex systems using multiple protocols:
import http from 'k6/http' ;
import { Client as MQTTClient } from 'k6/x/mqtt' ;
import redis from 'k6/x/redis' ;
import { check } from 'k6' ;
const redisClient = new redis . Client ( 'redis://localhost:6379' );
export default function () {
// HTTP API call
const res = http . post ( 'https://api.example.com/orders' , JSON . stringify ({
product: 'widget' ,
quantity: 1 ,
}));
check ( res , { 'order created' : ( r ) => r . status === 201 });
const orderId = res . json ( 'id' );
// Store in Redis
redisClient . set ( `order: ${ orderId } ` , res . body );
// Publish MQTT notification
const mqtt = new MQTTClient ();
mqtt . on ( 'connect' , () => {
mqtt . publish ( 'orders/new' , `Order ${ orderId } created` );
mqtt . end ();
});
mqtt . connect ( 'mqtt://localhost:1883' );
}
Best practices
Connection pooling Reuse connections in the init context when possible
Async operations Use async/await for non-blocking protocol operations
Error handling Always handle connection errors and timeouts
Resource cleanup Close connections in teardown or finally blocks
Next steps
Explore Extensions Discover more k6 extensions
Build Custom Binary Bundle extensions with xk6
xk6-disruptor Add chaos testing capabilities
Browser Extension Test frontend with browser automation