﻿---
title: Elastic OpenTelemetry data streams
description: Learn how {{edot}} stores OpenTelemetry signals in Elasticsearch. Understand OTel-native and ECS-compatible data streams, exporter behavior, storage engines, and how to configure data retention.
url: https://docs-v3-preview.elastic.dev/elastic/opentelemetry/pull/640/reference/data-streams
products:
  - Elastic Cloud Serverless
  - Elastic Distribution of OpenTelemetry Collector
  - Elastic Observability
applies_to:
  - Serverless Observability projects: Generally available
  - Elastic Stack: Generally available
---

# Elastic OpenTelemetry data streams
Elastic OpenTelemetry writes telemetry data to two types of data stream schemas in Elasticsearch:
- OTel-native data streams (default)
- ECS-compatible data streams (for backwards compatibility with APM)

This page provides a practical reference for which data streams Elastic OpenTelemetry uses, exporter behavior, storage engines, and how to configure data retention. For a detailed comparison of OTel data streams with classic APM and ECS-based integrations, refer to [OTel data streams compared to classic APM](https://docs-v3-preview.elastic.dev/elastic/opentelemetry/pull/640/reference/compatibility/data-streams).
To learn how to route OpenTelemetry (OTel) signals to custom data streams, refer to [Data stream routing](https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/solutions/observability/apm/opentelemetry/data-stream-routing).

## Exporter behavior

Elastic OpenTelemetry uses the `otel` exporter by default, which sends data to OTel-native data streams. For backwards compatibility with legacy APM data formats, Elastic OpenTelemetry can also use the `ecs` exporter, which sends data to ECS-compatible data streams.

## Data streams used by a local deployment

When Elastic OpenTelemetry runs as a [local gateway or Collector](https://docs-v3-preview.elastic.dev/elastic/opentelemetry/pull/640/reference/architecture), it writes telemetry data to different data streams depending on the exporter configuration and data source:

### OTel-native mode

This is the default mode. When ingesting standard OTel signals, Elastic OpenTelemetry writes to:

| Signal             | Data stream                                                |
|--------------------|------------------------------------------------------------|
| Traces             | `traces-*.otel-*`                                          |
| Metrics            | `metrics-*.otel-*` (TSDB-backed using `mode: time_series`) |
| Logs               | `logs-*.otel-*`                                            |
| Aggregated metrics | `metrics-*.[1m\|10m\|60m].otel-*`                          |

These streams follow OTel naming conventions and field structures.

### ECS-compatible data streams

When ingesting data from APM agents using the `elasticapmintake` receiver, Elastic OpenTelemetry automatically routes data to ECS-compatible data streams. The `elasticapmintake` receiver determines the destination data stream and internally uses ECS-compatible formatting for compatibility with legacy APM Server behavior.
<note>
  The `elasticapmintake` receiver is intended for migration use cases from classic APM agents. For new deployments, we recommend using OTel SDKs with the default OTel-native data streams.
</note>

When the `ecs` exporter is explicitly enabled, Elastic OpenTelemetry writes to:
- `traces-apm-*`
- `metrics-apm.internal-*`
- `metrics-apm.*-*`
- `metrics-apm.*.[interval]-*`
- `logs-apm.error-*`
- `logs-apm.app.*-*`

These match legacy APM Server behavior.

## Managed OTLP Endpoint

The Elastic Cloud Managed OTLP Endpoint follows the same stream selection logic as local Elastic OpenTelemetry deployments:
- OTel-native streams for standard OTel telemetry
- ECS-compatible streams for APM-formatted events

The main difference is that Elastic Cloud Managed OTLP Endpoint is a managed cloud service that handles ingestion and storage, whereas local Elastic OpenTelemetry deployments require you to manage the Collector infrastructure yourself. Ingest and storage behavior remain consistent between both approaches.
To customize which data streams your telemetry is routed to, you can use [data stream routing](https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/solutions/observability/apm/opentelemetry/data-stream-routing) with `data_stream.dataset` and `data_stream.namespace` attributes.

## Field duplication

You may notice fields like:
- `resource.attributes.service.name`
- `service.name`

These are not true duplicates. Here's why:
- OTel defines attributes at multiple levels (for example: resource, span).
- Elastic OpenTelemetry stores resource attributes under `resource.attributes.*`, according to OTel specifications.
- Kibana dashboards and APM UI rely on ECS-style top-level fields like `service.name`.

For more information about how resource attributes are mapped to ECS fields and stored, refer to [Attributes and labels](https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/solutions/observability/apm/opentelemetry/attributes).
Elastic OpenTelemetry uses two mechanisms to bridge these models:
1. **Passthrough fields**: When fields are propagated from `resource.attributes` to top level (also for `scope.attributes` and `attributes`), Elastic OpenTelemetry uses passthrough fields with no storage overhead.
2. **Field copying**: Elastic OpenTelemetry performs some copying for specific fields for enrichment and compatibility purposes. This copying is separate from the passthrough mechanism. For example, conditionally copying `span.id` to `transaction.id`.

These mechanisms ensure that:
- Dashboards continue to function
- Filters and searches behave consistently
- OTel structure remains intact for downstream compatibility

This duplication is intentional.

## Storage engines

The storage engine used by Elastic OpenTelemetry depends on which data stream the data is sent to. Different data streams use different index templates, and the index templates determine which storage engine is used.
For example:
- When Elastic OpenTelemetry sends to OTel-native data streams (using the `otel` exporter), the data uses the storage engines configured for those data streams.
- When Elastic OpenTelemetry sends to ECS-compatible data streams (using `elasticapmintake` or the `ecs` exporter), the data uses the storage engines configured for those data streams.

Elastic OpenTelemetry uses the same index templates and mappings as the rest of the Observability solution.

## Data stream lifecycle and retention

Elastic OpenTelemetry data streams have no default retention period. Backing indices roll over when they reach 50 GB or 30 days old, but data is not automatically deleted unless you configure a delete phase.

### Elastic Cloud Hosted and self-managed deployments

OTel-native Elastic OpenTelemetry data streams use the built-in ILM policies `logs`, `metrics`, and `traces@lifecycle`, as set by the `logs@settings`, `metrics@tsdb-settings`, and `traces@settings` component templates that the OTel index templates compose in Elasticsearch. To customize retention without modifying those managed policies, create a `@custom` component template for the relevant signal type:

| Signal  | Component template    |
|---------|-----------------------|
| Logs    | `logs-otel@custom`    |
| Metrics | `metrics-otel@custom` |
| Traces  | `traces-otel@custom`  |

When created, these component templates are automatically picked up by the corresponding OTel index template. For step-by-step instructions, refer to [Customize built-in ILM policies](https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/manage-data/lifecycle/index-lifecycle-management/tutorial-customize-built-in-policies).

### Elastic Cloud Serverless

Use [Data Stream Lifecycle (DSL)](https://docs-v3-preview.elastic.dev/elastic/docs-content/tree/main/manage-data/lifecycle/data-stream) to configure retention. Configuration is the same as for any other Elasticsearch data stream.