Prometheus can’t directly store metrics itself; instead, it scrapes them from configured targets, and if you want to send metrics to Prometheus for storage, you’re looking at Prometheus Remote Write.
Let’s see it in action. Imagine you have a k6 load test running, and you want to send its metrics to a Prometheus instance for long-term storage and querying.
Here’s a typical k6 configuration using the Prometheus Remote Write exporter:
import http from 'k6/http';
import { Trend, Gauge, Counter } from 'k6/metrics';
import { SharedArray } from 'k6/data';
// Configure Prometheus Remote Write
export const options = {
scenarios: {
constant_request_rate: {
executor: 'constant-arrival-rate',
preAllocatedVUs: 100,
maxVUs: 200,
rate: 200,
timeUnit: '1s',
},
},
// This is the key part for Remote Write
// Replace with your Prometheus endpoint
// Ensure your Prometheus is configured to receive remote write data
setupTimeout: '1m', // Increase setup timeout if needed
setup
{
url: 'http://localhost:9091/write', // Your Prometheus Remote Write endpoint
// Optional: Add headers if your Prometheus endpoint requires authentication
// headers: {
// 'Authorization': 'Bearer YOUR_TOKEN',
// },
// Optional: Batching configuration
// batchIntervals: '5s', // Send metrics every 5 seconds
// batchSize: 1000, // Send up to 1000 metrics per batch
},
};
// Example custom metrics
const responseTimes = new Trend('http_response_time');
const pendingRequests = new Gauge('http_pending_requests');
const failedRequests = new Counter('http_failed_requests');
export default function () {
const res = http.get('https://httpbin.org/get');
// Record metrics
responseTimes.add(res.timings.duration);
pendingRequests.add(http.getOptions().VU.current - http.getOptions().VU.completed); // Approximate pending
if (res.status >= 400) {
failedRequests.add(1);
}
// Simulate some work
// sleep(1);
}
In this example:
- The
setupblock withinexport const optionsis where you define your Prometheus Remote Write configuration. url: This is the critical piece – it’s the HTTP endpoint on your Prometheus server (or an intermediary like VictoriaMetrics or Mimir) that is configured to receive remote write data. Typically, this is/api/v1/writeor/writedepending on your Prometheus setup.headers: If your Prometheus endpoint requires authentication (e.g., API keys, tokens), you’d include them here.batchIntervalsandbatchSize: These allow you to control how k6 batches metrics before sending them. This can be useful for optimizing network traffic and Prometheus ingestion load.
When k6 runs with this configuration, it will collect all its internal metrics (VU count, iterations, etc.) and any custom metrics you define (like responseTimes, pendingRequests, failedRequests) and periodically send them in batches to the specified Prometheus endpoint. Prometheus, in turn, will ingest these metrics and store them in its time-series database.
This solves the problem of needing a separate agent or complex setup to get k6 metrics into your central monitoring system. k6 acts as both the load generator and the metric producer, pushing data directly to Prometheus.
The most surprising true thing about Prometheus Remote Write is that it’s a push mechanism, not a pull one like Prometheus’s core scraping. This means the client (in this case, k6) initiates the connection and sends data to the server (Prometheus), fundamentally changing the architectural assumptions about how metrics flow into Prometheus.
The exact levers you control are primarily around the client-side configuration in k6 (or your chosen client): the endpoint, batching strategies, and any authentication. On the Prometheus server side, the configuration needs to explicitly enable the remote write receiver and point it to the appropriate storage backend (e.g., a Prometheus TSDB, Cortex, Thanos, Mimir, VictoriaMetrics). Without the server-side configuration, the k6 push will simply fail, often with an HTTP 404 or 500 error.
The next concept you’ll likely explore is how to effectively query and visualize these ingested k6 metrics within Prometheus’s Grafana dashboards, or how to manage the cardinality of metrics generated by load tests.