Menu
Grafana Cloud

Get performance insights

Whenever you run a cloud test, Performance Insights algorithms automatically process the raw metrics and data.

If the cloud service finds an issue, it notifies you at the end of the test and provides recommendations for how to fix them.

There are four categories of performance insights:

  • HTTP load insights help diagnose issues with your system under test.
  • Best practices insights help diagnose issues with your test script.
  • Health alert insights help discover issues with your load generator.
  • Web vitals insights help you diagnose issues with your browser tests.

You can disable Performance Insights alerts, either for a single insight or a set of insights.

HTTP load alerts

HTTP load alerts happen when your test results have a high number of active requests or HTTP errors.

Throughput limit

Identifier: http_load_throughput_limit

  • Happens when: k6 detects a throughput limit. The number of active in-flight requests continues to grow as the number of Virtual Users increases, while the request rate (finished requests) stays flat.
  • What it might indicate: The system under test is overloaded, thus resulting in higher response times.
  • Recommendations: Correlate the performance bottleneck with data from an APM or server monitoring tool. After you make your changes, rerun your tests at the same VU level so you can verify whether your changes have improved performance.

Increased HTTP failure rate

Identifier: http_load_increased_http_failure_rate

  • Happens when: k6 detects a period of elevated HTTP errors (10% higher than the beginning of the test).
  • What it might indicate:
    • Web server configuration issues (timeouts, rate limiting, etc.)
    • Internal errors caused by saturation of a resource (CPU, memory, disk I/O or database connections). Saturation typically means the target system is close to its performance limit.

Caution

Failed responses are often returned much faster than successful responses.

Consequently, an increased HTTP failure rate may produce misleading metrics for request rates and response times.

High HTTP failure rate

Identifier: http_load_high_http_failure_rate

  • Happens when: The total number of HTTP or HTTPS errors is higher than 15% during the first 100 completed script iterations.

  • What it might indicate: Errors that occur early in a test are often not performance-related. Instead, your script might be making invalid requests:

    • Invalid URLs, such as URLs with typos or hostnames outside the public DNS system.
    • Missing required headers, such as authentication, authorization, or user-agents.
    • Sending the wrong body data.

    The system under test also might be intentionally limiting requests:

    • It may be behind a firewall.
    • It may have a rate limit that your test is reaching.
  • Recommendations: Check that your script is valid and that it can properly access the system.

    • Run a single iteration of the script locally to troubleshoot the failing requests running a load test.
    • In the script, verify that the failing requests are formulated correctly and return the expected response.
    • Verify that any user accounts have sufficient permissions to access the application.
    • Verify that the application is publicly accessible.

Caution

Failed responses are often returned much faster than successful responses.

Consequently, an increased HTTP failure rate may produce misleading metrics for request rates and response times.

Not enough training data

Identifier: best_practice_not_enough_training_data

  • Happens when: Your test didn’t complete the 100 VU iterations necessary for the training data. To be meaningful, Performance Insights need at least 100 complete VU iterations of training data plus an additional 15 seconds.
  • Recommendations: Increase the test duration or number of iterations.

Duration too short

Identifier: best_practice_duration_too_short

  • Happens when: k6 detects more than 100 complete VU iterations, but the duration needs to be extended to properly analyze data. Similar to Not Enough Training Data, this alert is raised because k6 doesn’t have enough training data to produce meaningful results.
  • Recommendations: Increase the test duration or number of iterations.

Best practice alerts

Best practices alerts happen when your test script generates either too much or too little data to be useful.

These issues can either skew your results or make results harder to analyze and parse. These alerts are often quickly solved with changes in the test script or test configuration.

Third-party content

Identifier: best_practice_third_party_content

  • Happens when: k6 detects many different domains in a test.
  • What it might indicate: Your test script contains requests to third-party resources such as CDNs, social media scripts, analytics tools, etc.
  • Recommendations: Remove third-party requests:
    • The requests may violate the third party’s ToS.
    • The third party may throttle your requests, skewing the percentiles of your results.
    • You may have no ability to affect that third party’s performance.
  • You might have valid reasons to ignore this alert:
    • Your system under test may use multiple domains, in which case you can ignore this alert.
    • You also may have a valid reason to test your CDN. However, most CDNs charge based on usage, so your tests could generate additional costs from your CDN.

Too many URLs

Identifier: best_practice_too_many_urls

  • Happens when: k6 detects more than 500 unique URLs in your test results.
  • What it might indicate: The URL might contain a query parameter or other ID that’s unique per iteration, such as tokens, session IDs, etc. In the following example, the query parameter would produce a large number of URL metrics:
JavaScript
import http from 'k6/http';

for (let id = 1; id <= 600; id++) {
  http.get(`http://test.k6.io/?ts=${id}`);
}
// But you can group all these URL metrics together
// in our result analysis using the name tag,
// making it easier for you to interpret the data.
// Note that you must use the name tag for grouping.

for (let id = 1; id <= 600; id++) {
  http.get(`http://test.k6.io/?ts=${id}`, {
    tags: { name: 'test.k6.io?ts' },
  });
}
  • Recommendations: Aggregate dynamic URLs as it can make analysis easier. To see how, refer to URL Grouping.

Note

In some cases, the unique URLs may belong to third parties. As mentioned in the Third Party Content alert, best practices recommend excluding third-party resources in your test scripts.

Too many groups

Identifier: best_practice_too_many_groups

  • Happens when: k6 detects a high number of groups in your test script.
  • What it might indicate: This alert commonly happens when a test uses a Group name to aggregate different HTTP requests or puts the group name in a loop statement.
  • Recommendations:
    • Use the name tag to aggregate URLs.
    • Add Group names in your test script.
    • If you want to group multiple HTTP requests, use URL grouping to aggregate data in a single URL metric.

Too many metrics

Identifier: best_practice_too_many_metrics

  • Happens when: k6 detects a high number of metrics in your test script.
  • Recommendations: Considering k6 can generate two types of metrics (built-in and custom), there are two things to check:
    • Whether your script contains too many unique URLs.
    • Whether it generates custom metrics in a loop.

Having too many metrics in a single test is considered an anti-pattern because it makes result analysis difficult.

The following example shows how custom metrics can be misused:

JavaScript
import http from 'k6/http';
import { Counter } from 'k6/metrics';

const successCounts = [];
for (let id = 1; id <= 1000; id++) {
  successCounts.push(new Counter(`successCount_${id}`));
}
for (let id = 1; id <= 1000; id++) {
  const response = http.get(`http://test.k6.io/?ts=${id}`);
  successCounts[id].add(response.status === 200);
}
// k6 can count responses by status codes on its own.
// Additionally, URLs should be grouped as it's shown
// in Too Many URLs alert example.

Too many time series

Identifier: best_practice_too_many_time_series

  • Happens when: k6 detects a high number of time series in your test script.
  • What it might indicate: This alert commonly happens when a test has an excessive number of unique values for tags.
  • Recommendations:
    • Use URL grouping to aggregate data in a single URL metric.
    • Use fewer tag values when using custom tags.
    • If you followed all previous recommendations and still get this alert, use drop_metrics and drop_tags to reduce the cardinality of time series.

Outdated k6 release used

Identifier: best_practice_outdated_k6_release_used

  • Happens when: You use a legacy version of k6 that is significantly older than the latest stable version.
  • Recommendations:
    • Install the latest release of k6, or upgrade your existing packages.
    • Update the k6 binary that your CI/CD pipeline uses to run tests.
    • If you’re part of an organization or team, collectively decide on a version of k6 to use going forward for consistency and ease of comparison.

Invalid metric names

Identifier: best_practice_invalid_metric_names

  • Happens when: You tag your custom metrics with invalid names.
  • Recommendations:
    • Ensure your custom metric names comply with OpenTelemetry and Prometheus limitations. Such as:
      • Only contain valid symbols of ASCII letters, numbers, or _.
      • Metric names must not start with a number.

Health alerts

Health alerts happen when the load generator has high resource utilization.

Caution

An overutilized load generator can skew test results.

High load generator CPU usage

Identifier: health_high_loadgen_cpu_usage

  • Happens when: k6 detects high utilization of the load-generator CPU during a test. Overutilization of the load generator can skew your test results, producing data that varies unpredictably from test to test. Virtual Users will naturally try to execute as quickly as possible.
  • What it might indicate: The exact cause of overutilization varies, but the following reasons are most likely:
    • Lack of sleep times in your scripts. Sleep times help pace and emulate real user behavior.
    • High RPS per VU. When testing API endpoints, you may configure your test to aggressively request an endpoint.
    • Large numbers of requests in a single request batch. Requests made in a request batch are parallelized up to the default or defined limits.
    • Large amounts of data are returned in responses, resulting in high memory utilization.
    • When the memory of the load generator reaches near total consumption, the garbage-collection efforts of the load generator can increase CPU utilization.
    • A JavaScript exception is being thrown early in VU execution, resulting in an endless restart loop until all CPU cycles are consumed.
  • Recommendations:
    • Increase sleep times where appropriate.
    • Increase the number of VUs to produce less RPS per VU (thus the same total load).
    • Use multiple load zones to spread VUs across multiple regions.

High load generator memory usage

Identifier: health_high_loadgen_mem_usage

  • Happens when: k6 detects high utilization of load-generator memory during a test. When memory utilization is high, the results might have unexpected behavior or failures. High memory utilization may also cause high CPU utilization, as garbage-collection efforts consume more and more CPU cycles.
  • Recommendations:
    • Use the test option discardResponseBodies to throw away the response body by default
    • Use responseType: to capture the response bodies you may require

Web vitals alerts

Web vitals alerts happen when your test script includes browser tests and k6 detects any web vitals scores that are: good, needs improvement, or poor.

These alerts can give you an indication of the user experience when accessing your website, and each web vital has a different set of recommendations for how to improve it.

Note

Web Vitals is an initiative by Google to provide unified guidance for quality signals that are essential to delivering a great user experience on the web. Refer to Web Vitals to learn more about the initiative and what each metric represents.

Cumulative Layout Shift (CLS)

Identifier: web_vital_cls

Cumulative Layout Shift (CLS) measures the visual stability on a webpage by quantifying the amount of unexpected layout shift of visible page content. Improving CLS is essential for providing a more predictable and pleasant user experience.

  • Happens when: k6 detects a slight or considerable shift in the page layout.
  • Recommendations:
    • Find out the root cause of what’s causing a high CLS score by using the Chrome UX Report (CrUX) and PageSpeed Insights.
    • Set Dimensions for Images and Videos: Reserve space for images and videos by specifying their dimensions in the HTML. This prevents the page content from shifting when these elements load.
    • Use CSS Transitions for Animations: If you have animations on your page, use CSS transitions instead of JavaScript animations. CSS transitions are less likely to cause layout shifts.
    • Preload and Preconnect: Use the preload and preconnect hints to give the browser a heads-up about resources that will be needed soon. This can help to load resources earlier and reduce the chance of layout shifts.
    • Lazy Load Elements Below the Fold: Defer the loading of images and other non-critical resources until they’re about to be scrolled into the viewport.
    • Avoid Dynamically Injected Content: If you’re injecting content dynamically, make sure to reserve space for it in the layout or use placeholders.
    • Optimize Font Loading: Use the font-display: swap; property in your CSS to ensure text is rendered with a fallback font until the custom font is loaded.
    • Optimize Third-Party Embeds: If using third-party embeds, like social media widgets or iframes, ensure they reserve the required space and don{"’"}t cause unexpected shifts. Some embed codes provide specific attributes or customization options to control layout behavior.
    • Testing on Different Devices and Resolutions: Test your website on various devices and screen resolutions to ensure that layout shifts are minimized across different contexts.
    • Implementing a Loading Skeleton: Use loading skeletons or placeholders for content that is about to load. This gives users a visual indication of where the content will appear and reduces the perceived impact of shifts.

First Contentful Paint (FCP)

Identifier: web_vital_fcp

First Contentful Paint (FCP) measures the time it takes for the first content element to be painted on the screen. A faster FCP contributes to a better user experience.

  • Happens when: k6 detects that the first content element to be painted on the screen took longer than the recommended thresholds. A warning means the content took longer than 1.8 seconds, and a failure means the content took longer than 2.5 seconds.
  • Recommendations:
    • Minimize Server Response Time (TTFB): Efficient server responses contribute to faster content rendering. Employ caching mechanisms and consider upgrading your hosting plan for better server performance.
    • Minimize Render-Blocking Resources: Identify and address render-blocking resources, especially JavaScript and CSS files. Utilize techniques such as asynchronous loading or defer loading for non-critical resources.
    • Prioritize Above-the-Fold Content: Ensure that above-the-fold content, the content visible without scrolling, is prioritized for loading. This involves optimizing the delivery of critical resources and minimizing the number of requests needed to render this content.
    • Optimize Images and Videos: Compress and optimize images to reduce their file size without sacrificing quality. Consider using modern image formats like WebP. Also, lazy load images and videos to defer loading until they’re needed, improving initial page load times.
    • Optimize Web Fonts: Minimize the use of custom web fonts or use the font-display: swap; property to ensure text is visible even before the custom font has fully loaded.
    • Browser Caching: Implement proper caching strategies for static assets. Utilize cache headers to instruct the browser to store and reuse resources locally, reducing the need to download them on subsequent visits.
    • Use a Content Delivery Network (CDN): Deploy a Content Delivery Network to distribute your content across servers globally. This reduces latency and speeds up content delivery, improving FCP.
    • Reduce Third-Party Scripts: Limit the use of third-party scripts as they can introduce additional delays. Only include essential third-party scripts and load them asynchronously to prevent them from blocking rendering.

First Input Delay (FID)

Identifier: web_vital_fid

First Input Delay (FID) measures the responsiveness of a web page by quantifying the delay between a user’s first interaction, such as clicking a button, and the browser’s response. Improving FID is essential for providing a more responsive and interactive user experience.

  • Happens when: k6 detects that there was a delay above the threshold between the user’s first interaction and the browser’s response in your test script. A warning means the delay exceeded 0.1 seconds, and a failure means the delay exceeded 0.3 seconds.
  • Recommendations:
    • Async and Defer Attribute for Scripts: Use the async or defer attribute when including scripts in your HTML. This allows the browser to continue parsing the HTML without blocking, resulting in a faster page load.
    • Optimize JavaScript Execution: Minimize and optimize JavaScript code to reduce execution time. Eliminate unnecessary scripts, and consider code splitting to load only the necessary JavaScript for the current view.
    • Optimize Third-Party Scripts: Limit the use of third-party scripts, and if necessary, load them asynchronously. Third-party scripts can significantly contribute to FID if they’re large or cause delays in execution.
    • Web Workers: Consider using Web Workers to offload heavy JavaScript tasks to a separate thread, preventing them from blocking the main thread and improving responsiveness.

Interaction to Next Paint (INP)

Identifier: web_vital_inp

Interaction to Next Paint (INP) is a metric that assesses a page’s overall responsiveness to user interactions by observing the latency of all click, tap, and keyboard interactions that occur throughout the lifespan of a user’s visit to a page.

  • Happens when: k6 detects that the longest interaction observed was above the recommended threshold (excluding outliers). A warning means the delay exceeded 0.2 seconds, and a failure means the delay exceeded 0.5 seconds.
  • Recommendations:
    • Optimize JavaScript Execution: Minimize and optimize JavaScript code. Remove unnecessary scripts, and consider using code splitting to load only essential JavaScript for the current view.
    • Async and Defer Attribute for Scripts: Use the async or defer attribute when including scripts in your HTML. This allows the browser to continue parsing the HTML without blocking, resulting in a faster page load and reduced INP.
    • Web Workers: Consider using Web Workers to offload heavy JavaScript tasks to a separate thread, preventing them from blocking the main thread and improving responsiveness.
    • Optimize Third-Party Scripts: Limit the use of third-party scripts, and if necessary, load them asynchronously. Third-party scripts can significantly contribute to INP if they’re large or cause delays in execution.
    • Minimize DOM size: When a webpage’s Document Object Model (DOM) is small, rendering tasks are usually quick. However, as the DOM size increases, rendering work tends to scale, leading to a non-linear relationship. Large DOMs pose challenges during the initial page render, requiring substantial rendering work, and during user interactions, where updates can be expensive, delaying the presentation of the next frame.

Largest Contentful Paint (LCP)

Identifier: web_vital_lcp

Largest Contentful Paint (LCP) measures the time it takes for the largest content element on a page to become visible. Improving LCP contributes significantly to a better user experience.

  • Happens when: k6 detects that the time to load the largest content element on the page exceeded the recommended threshold. A warning means the load time exceeded 2.5 seconds, and a failure means the load time exceeded 4 seconds.
  • Recommendations:
    • Minimize Server Response Time (TTFB): Efficient server responses contribute to faster content rendering. Employ caching mechanisms and consider upgrading your hosting plan for better server performance.
    • Minimize Render-Blocking Resources: Identify and address render-blocking resources, especially JavaScript and CSS files. Utilize techniques such as asynchronous loading or defer loading for non-critical resources.
    • Prioritize Above-the-Fold Content: Ensure that above-the-fold content, the content visible without scrolling, is prioritized for loading. This involves optimizing the delivery of critical resources and minimizing the number of requests needed to render this content.
    • Optimize Images and Videos: Compress and optimize images to reduce their file size without sacrificing quality. Consider using modern image formats like WebP. Also, lazy load images and videos to defer loading until they are needed, improving initial page load times.
    • Optimize Web Fonts: Minimize the use of custom web fonts or use the font-display: swap; property to ensure text is visible even before the custom font has fully loaded.
    • Browser Caching: Implement proper caching strategies for static assets. Utilize cache headers to instruct the browser to store and reuse resources locally, reducing the need to download them on subsequent visits.
    • Use a Content Delivery Network (CDN): Deploy a Content Delivery Network to distribute your content across servers globally. This reduces latency and speeds up content delivery, improving FCP.
    • Reduce Third-Party Scripts: Limit the use of third-party scripts as they can introduce additional delays. Only include essential third-party scripts and load them asynchronously to prevent them from blocking rendering.

Time to First Byte (TTFB)

Identifier: web_vital_ttfb

Time to First Byte (TTFB) measures the time between the request for a resource and when the first byte of a response begins to arrive. It’s a foundational web performance metric that precedes every other meaningful user experience metric such as First Contentful Paint and Largest Contentful Paint. A high TTFB value adds time to the metrics that follow it.

Even though it’s a foundational metric, it isn’t a part of Google’s Core Web Vitals. That’s because depending on the technology you use for your website, a high TTFB metric might not be as impactful as other metrics. For example, for Single Page Application (SPAs), having a low TTFB score is important so that the client can start rendering elements as soon as possible. On the other hand, for a server-rendered site, a high TTFB score might not have as much of an impact on other metrics.

  • Happens when: k6 detects that the time between the request for a resource and when the first byte begins to arrive has exceeded the recommended threshold. A warning means the time exceeded 0.8 seconds, and a failure means the time exceeded 1.8 seconds.
  • Recommendations:
    • Upgrade Hosting Plan: Consider upgrading your hosting plan to one that offers better resources, especially if your website is currently on shared hosting. Dedicated or VPS hosting may provide better performance and a lower TTFB.
    • Optimize Server Configuration: Ensure your server is configured for optimal performance. This includes adjusting server settings, such as connection timeouts and keep-alive settings, to minimize delays.
    • Content Delivery Network (CDN): Utilize a CDN to distribute static assets geographically closer to users. This helps in reducing latency and improving TTFB by serving content from servers located nearer to the user.
    • Server-Side Caching: Implement server-side caching mechanisms to store and serve frequently requested content without re-generating it for each user. This can significantly reduce the TTFB by delivering cached content when possible.
    • Compression: Enable compression for your web server to reduce the size of data sent to the browser. Gzip or Brotli compression can be particularly effective in minimizing the time it takes to transmit resources.
    • Optimize Database Queries: Review and optimize database queries to ensure they are efficient. Use indexes where necessary, and minimize the number of database queries required to generate a page.
    • Minimize Redirects: Minimize the use of redirects, as each redirect introduces an additional round-trip delay. Where possible, ensure that URLs are structured to minimize unnecessary redirects.
    • Browser Caching: Leverage browser caching by setting appropriate cache headers for static resources. This can reduce the need for the browser to request the same resources on subsequent visits.
    • Use Preconnect and Prefetch: Implement preconnect and prefetch directives in your HTML to establish early connections to essential third-party domains and prefetch resources needed for subsequent navigation, respectively.

Disabling performance insights

You can disable one or more insights from showing up when executing load tests by using the ext.loadimpact.insights property in the options variable:

JavaScript
export const options = {
  ext: {
    loadimpact: {
      insights: {
        disabled: ['http_load_throughput_limit', 'health_high_loadgen_cpu_usage'],
      },
    },
  },
};

When you provide the disabled array, k6 omits all results from the result analysis. In contrast, you can provide a list of enabled insights, excluding all other insights from analysis.

JavaScript
export const options = {
  ext: {
    loadimpact: {
      insights: {
        enabled: ['http_load_high_http_failure_rate'],
      },
    },
  },
};

In the preceding example, only one insight will be shown (given that the script executes with a high HTTP failure rate).

You can also enable or disable multiple insights by their category (also called “set”). To achieve this, specify the enabledSets or disabledSets array in the insights object.

JavaScript
export const options = {
  ext: {
    loadimpact: {
      insights: {
        enabledSets: ['http_load'],
      },
    },
  },
};

Or alternatively:

JavaScript
export const options = {
  ext: {
    loadimpact: {
      insights: {
        disabledSets: ['best_practice', 'health'],
      },
    },
  },
};

For all insights and their identifiers, refer to the table below:

NameIdentifierSet Identifier
Throughput Limithttp_load_throughput_limithttp_load
Increased HTTP failure ratehttp_load_increased_http_failure_ratehttp_load
High HTTP failure ratehttp_load_high_http_failure_ratehttp_load
Not Enough Training Databest_practice_not_enough_training_databest_practice
Duration Too Shortbest_practice_duration_too_shortbest_practice
Third Party Contentbest_practice_third_party_contentbest_practice
Too Many URLsbest_practice_too_many_urlsbest_practice
Too Many Groupsbest_practice_too_many_groupsbest_practice
Too Many Metricsbest_practice_too_many_metricsbest_practice
Outdated k6 Release Usedbest_practice_outdated_k6_release_usedbest_practice
High Load Generator CPU Usagehealth_high_loadgen_cpu_usagehealth
High Load Generator Memory Usagehealth_high_loadgen_mem_usagehealth
Cumulative Layout Shiftweb_vital_clsweb_vitals
First Contentful Paintweb_vital_fcpweb_vitals
First Input Delayweb_vital_fidweb_vitals
Interaction to Next Paintweb_vital_inpweb_vitals
Largest Contentful Paintweb_vital_lcpweb_vitals
Time to First Byteweb_vital_ttfbweb_vitals