# Elastic APM Transaction Sample Rate: Setup and Checks

> Set ELASTIC_APM_TRANSACTION_SAMPLE_RATE, check why it seems ignored, and map the setting to OpenTelemetry sampling during a migration.

- Published: 2026-09-24T00:00:00.000Z
- Updated: 2026-09-24T00:00:00.000Z
- Author: Terry Osayawe
- Tags: elastic-apm, trace-sampling, opentelemetry, distributed-tracing
- Canonical: https://tracekit.dev/blog/elastic-apm-transaction-sample-rate

`ELASTIC_APM_TRANSACTION_SAMPLE_RATE` sets the fraction of new transactions that an Elastic APM agent samples. Set `0.2` to sample about 20% of eligible new traces, or `1.0` to sample all of them. The value must be between `0.0` and `1.0`. An incoming distributed trace can carry an earlier sampling decision, so changing this setting may not change every request you see.

This guide covers the setting, the common reasons it appears to do nothing, and the OpenTelemetry setting to use during migration. It uses current [Elastic Node.js configuration](https://www.elastic.co/docs/reference/apm/agents/nodejs/configuration), [Elastic Node.js performance guidance](https://www.elastic.co/docs/reference/apm/agents/nodejs/performance-tuning), and [OpenTelemetry SDK configuration](https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/).

## Set the Elastic APM transaction sample rate

Set the environment variable in the process that starts your application:

```bash
export ELASTIC_APM_TRANSACTION_SAMPLE_RATE=0.2
node server.js
```

For the Elastic Node.js agent, the equivalent code option is `transactionSampleRate`:

```js
require('elastic-apm-node').start({
  serviceName: 'checkout-api',
  transactionSampleRate: 0.2,
})
```

Start the agent before loading modules that it must instrument. Use one configuration method for a first test. Then confirm which setting wins when you add other sources.

| Value | Meaning for a new sampling decision |
| --- | --- |
| `1.0` | Sample every eligible new trace. |
| `0.2` | Sample about one in five eligible new traces over enough traffic. |
| `0.01` | Sample about one in 100 eligible new traces over enough traffic. |
| `0.0` | Do not sample new trace details at this decision point. |

These are probabilities, not fixed intervals. A batch of 20 requests need not contain exactly four sampled traces. [Elastic's Node.js documentation](https://www.elastic.co/docs/reference/apm/agents/nodejs/configuration) gives `1.0` as the default for this agent. The [Python](https://www.elastic.co/docs/reference/apm/agents/python/configuration) and [Go](https://www.elastic.co/docs/reference/apm/agents/go/configuration) agent references also document this environment variable and their defaults. Check your agent's own version and configuration page before applying a rule across languages.

## What the setting changes

Elastic's transaction sample rate is a head-based decision. The agent chooses whether to keep trace detail when a new trace starts. A lower rate can reduce tracing overhead and stored detail, but it also makes rare failures less likely to appear with a complete trace. [Elastic's Node.js performance guide](https://www.elastic.co/docs/reference/apm/agents/nodejs/performance-tuning) describes that tradeoff.

The setting does not mean “keep every error and slow request.” At the start of a request, the agent does not yet know its final duration or outcome. If you need a different retention policy, evaluate your full tracing pipeline and its sampling options. Do not treat a simple probability setting as an error-retention promise.

Also separate trace detail from other telemetry. Agent versions and APM Server versions differ in what they report for unsampled transactions. Do not infer metric or error coverage from a trace-detail count alone. Check the documentation for your installed agent and server versions.

## Why the sample rate seems ignored

### An upstream service already chose the rate

A request can arrive with a W3C `traceparent` header. Its sampled flag may carry the decision from the service that started the distributed trace. Elastic's [Node.js performance guide](https://www.elastic.co/docs/reference/apm/agents/nodejs/performance-tuning) says `transactionSampleRate` does not apply when the incoming trace already has that decision.

Test both cases:

1. Send a request that starts a new trace at this service.
2. Send a request with an upstream `traceparent` header.
3. Compare the sampled flags and trace IDs across the service boundary.

If only the second case differs, inspect the upstream sampler. Raising this service's local rate will not repair a decision made earlier.

### A higher-priority setting overrides the environment variable

For the Elastic Node.js agent, [central configuration has higher precedence](https://www.elastic.co/docs/reference/apm/agents/nodejs/configuring-agent) than environment variables. Environment variables take precedence over the `apm.start()` object and the agent configuration file.

Check the effective setting in this order:

1. APM agent central configuration for the service and environment.
2. The environment of the running application process.
3. The object passed to `apm.start()`.
4. The agent configuration file.

Do not assume an environment variable in your shell reached a container, process manager, or serverless runtime. Read the deployed process configuration through your normal operations tooling. Keep credentials out of diagnostic output.

### The test has too few requests

A probability needs enough independent new traces to show its pattern. Ten requests at `0.2` can produce a count far from two without a configuration fault. Use a larger test set, one route, and a stable deployment window. Count root traces, not child spans.

A useful check records the configured value, application instance, root trace count, sampled trace count, and upstream `traceparent` state. Then compare the same fields after the change. This method does not require a made-up target percentage for a small sample.

## Map the setting to OpenTelemetry during migration

`ELASTIC_APM_TRANSACTION_SAMPLE_RATE` belongs to an Elastic agent. It does not configure an OpenTelemetry SDK. For a head-based ratio in an OpenTelemetry SDK that supports these environment variables, set both values:

```bash
export OTEL_TRACES_SAMPLER=parentbased_traceidratio
export OTEL_TRACES_SAMPLER_ARG=0.2
```

The [OpenTelemetry SDK configuration reference](https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/) defines `parentbased_traceidratio` as a parent-based sampler with a trace-ID ratio decision at a new root. It also says environment-variable support varies by language. Verify your SDK's support and effective sampler before a cutover.

| Question | Elastic APM agent | OpenTelemetry SDK |
| --- | --- | --- |
| Which setting controls a new trace ratio? | `ELASTIC_APM_TRANSACTION_SAMPLE_RATE` | `OTEL_TRACES_SAMPLER` with `OTEL_TRACES_SAMPLER_ARG` |
| What represents 20%? | `0.2` | `parentbased_traceidratio` and `0.2` |
| What about a sampled parent? | Agent follows distributed context where supported. | Parent-based sampler follows the parent decision. |
| Is the result identical? | No guaranteed one-to-one trace set. | Verify behavior in your own pipeline. |

Equal ratios do not guarantee identical retained traces. The agents can differ in instrumentation coverage, parent handling, and effective configuration. Compare root and child spans for the same service, route, and traffic class. The [parallel OpenTelemetry migration guide](/blog/migrate-to-opentelemetry-without-downtime) explains how to compare both paths before removing the old agent.

## Where Tracekit fits after sampling

Tracekit [accepts OTLP traces](/docs/integration/overview) from an OpenTelemetry exporter. It can show the traces that your instrumentation and sampling pipeline send. It cannot restore a trace that the SDK or an earlier service never recorded.

For a migration, first verify one complete trace at a high sampling rate in a controlled environment. Check the service name, root span, downstream spans, and parent links. Then tune the rate against your traffic and investigation needs. Use the [distributed tracing guide](/features/distributed-tracing) for the trace view and the [sampling optimizer](/tools/sampling-optimizer) for a planning estimate. A calculator is a planning aid; production trace coverage is the final check.

## Final verification checklist

- [ ] The value is between `0.0` and `1.0`.
- [ ] The deployed process received the setting.
- [ ] Central configuration does not override it.
- [ ] The test starts new traces as well as continuing upstream traces.
- [ ] The count uses root traces, not spans.
- [ ] The chosen rate retains enough evidence for the failures you investigate.
- [ ] The OpenTelemetry sampler is verified separately during migration.

If the rate still appears wrong, start with the effective agent configuration and incoming `traceparent`. Those two checks usually narrow the problem before you change the sampling number again.
