---
title: "How to configure sampling in Faro | Grafana Cloud documentation"
description: "Faro's built-in session tracker to create, resume and extend sessions and to provide sampling capabilities based on user sessions."
---

> For a curated documentation index, see [llms.txt](/llms.txt). For the complete documentation index, see [llms-full.txt](/llms-full.txt).

# How to configure sampling in Faro

Faro makes sampling decisions on a per user-session basis. For sampled sessions, Faro samples and transmits every signal. Faro discards signals from un-sampled sessions.

Faro uses the configured sampling rate or a custom sampling function to determine what to sample. The sampling rate and sampling function need to set or return a sampling rate between 0 and 1. Where 0 is no signals sent and 1 is all. By default, Faro uses a sampling rate of 1.

The sampling function computes a sampling decision based on other properties for customer sampling needs. It gets contextual information injected, including multiple Faro Metadata objects.

Faro calculates a sampling decision:

- On page load, when Faro initializes and finds an invalid session in web-storage
- On session extend, when Faro auto-creates a new session or when you manually call `setSession(...)`

> Note
> 
> Faro uses a session-based sampling configured within the session configuration object. Consult the [session tracking documentation](/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/session-tracking/) to understand how Faro tracks and handles sessions and how to configure the session manager.

## How to ensure sampling consistency between frontend and backend

Faro uses a head based sampling approach based on sessions. If a session isn’t part of a sample, Faro doesn’t send any data for that specific session, see the preceding section.

To ensure consistency between the sampled frontend and backend data it’s recommended to configure your backends to use `parent-based` sampling.

> Note
> 
> Parent-based sampling is a technique to control sampling in a way that’s consistent across the different components of a distributed system. It ensures that a sampling decision propagates to all subsequent components that are part of the journey of a request.

If you use Faro’s [web-tracing](/docs/grafana-cloud/monitor-applications/frontend-observability/instrument/tracing-instrumentation/) instrumentation, Faro tells the underlying tracing instrumentation the sampling result which sets the W3C sampled flag to inform subsequent instruments to record spans.

If you use OpenTelemetry for your backend instrumentation, you should set a `parent-based` sampler. For more information, refer to OpenTelemetry docs for the [parent-based sampler](https://opentelemetry.io/docs/languages/erlang/sampling/#parentbasedsampler).

Be aware of the consequence of this consistency. A `parent-based` sampler follows the decision it receives, so when a session isn’t part of the sample, your backend joins the trace but doesn’t record the server span. As a result, lowering the Faro sampling rate therefore reduces backend traces as well as frontend ones. If that isn’t what you want, refer to the following section.

## How to keep backend sampling independent of the frontend

Use this approach when your backend services apply their own sampling, for example tail sampling in a collector, and you don’t want the frontend sampling rate to reduce backend traces.

For an un-sampled session, Faro’s web-tracing instrumentation still adds a `traceparent` header to outgoing `fetch` and `XMLHttpRequest` requests. The header carries a sampled flag of `00` (not sampled).

Backend OpenTelemetry SDKs use a `parent-based` sampler by default, so they honor that flag and don’t record the span.

Set `omitTraceContextForUnsampledSessions` on the tracing instrumentation to leave the header out entirely for un-sampled sessions. Each backend service then applies its own sampling rules to those requests.

ts ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```ts
import { getWebInstrumentations, initializeFaro } from '@grafana/faro-web-sdk';
import { TracingInstrumentation } from '@grafana/faro-web-tracing';

initializeFaro({
  ...
  sessionTracking: {
    samplingRate: 0.1,
  },
  instrumentations: [
    ...getWebInstrumentations(),
    new TracingInstrumentation({ omitTraceContextForUnsampledSessions: true }),
  ],
});
```

Sampled sessions are unaffected. They continue to send a `traceparent` with a sampled flag of `01`, and your backend joins and records the frontend trace.

The following table summarizes the behavior:

Expand table

| Session    | Option            | `traceparent` sent | Backend result                       |
|------------|-------------------|--------------------|--------------------------------------|
| Sampled    | Either value      | Sampled flag `01`  | Joins the trace and records the span |
| Un-sampled | `false` (default) | Sampled flag `00`  | Joins the trace but records nothing  |
| Un-sampled | `true`            | Not sent           | Records the request as a new trace   |

Consider the following before you enable this option:

- Requests from un-sampled sessions start a new trace at your backend instead of continuing the frontend trace, so you can’t navigate from those traces back to a browser session. Faro already discarded every frontend span for an un-sampled session, so the frontend end of that link would hold no data.
- If you supply your own `propagator`, this option withholds everything that propagator writes for un-sampled sessions, including `tracestate` and `baggage`, not only `traceparent`.
- Requests from un-sampled sessions are sampled by your backend services, so they contribute to backend trace volume at whatever rate those services use.

## Set a sampling rate

Sets the sampling rate to 80% of sessions.

ts ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```ts
initializeFaro({
  ...
  sessionTracking?: {
    samplingRate: 0.8,
  }
```

## Use the sampler function to calculate custom sampling rates

Use a custom sampler function to calculate a tailored sampling decision. In this case different sampling decisions based on the planet name.

> Note
> 
> Defining sampling rates based on metadata or other properties can introduce bias in the sampling decisions. A custom sampler function is commonly used when running experiments in production or when there is an interest on specific types of traffic.

ts ![Copy code to clipboard](/media/images/icons/icon-copy-small-2.svg) Copy

```ts
initializeFaro({
  ...
  sessionTracking?: {
    sampler(context) {
      const planet = context.metas.user?.attributes?.['planet'];

      if (!planet) {
         return 0; // 0%
      }

      if (planet === 'mars') {
         return 0.8; // 80%
      }

      if (planet === 'moon') {
         return 0.3; // 30%
      }

      if (planet === 'earth') {
         return 0.1; // 10%
      }

      return 1;
    },
  };
});
```
