Ask a platform team how their services configure OpenTelemetry and the honest answer is usually "it depends on the service". One team sets a dozen OTEL_ variables in a Helm chart, another wires exporters in code, a third copied a sampler setting from a blog post two years ago. The result is telemetry that differs in quality across services for no good reason, and changes that require touching every repository.
OpenTelemetry's declarative configuration is designed to fix that, and the core of it is now stable.
What changed
In March 2026 the project marked key portions of the declarative configuration specification stable12:
- The JSON schema for the data model, released as
opentelemetry-configuration1.0.03. - The YAML file format and the in-memory representation of the model.
- The SDK operations to parse a file and create SDK components from it.
- A standard environment variable,
OTEL_CONFIG_FILE, to point the SDK at the file.
At the time, implementations existed in C++, Go, Java, JavaScript and PHP, with .NET and Python under way, and the Collector used the Go implementation for its own internal telemetry1. Since then, the Java Spring Boot starter has added support from version 2.26.0, embedding the same schema in application.yaml4.
Why it matters
Environment variables are flat. They can name an exporter endpoint, but struggle with a pipeline: several processors, different exporters per signal, views that drop noisy attributes, a sampler with rules. Anything beyond them meant code, or for the Java agent a separate extension jar4. The declarative schema describes the whole SDK pipeline as a tree, in the same shape the SDK runs5:
file_format: "1.0"
resource:
attributes:
- name: service.name
value: checkout
tracer_provider:
processors:
- batch:
exporter:
otlp_http:
endpoint: ${OTEL_EXPORTER_OTLP_TRACES_ENDPOINT:-http://collector:4318/v1/traces}
Environment variable substitution keeps the parts that genuinely vary per environment out of the file, while everything else becomes a reviewable artefact.
Telemetry configuration is platform policy. It belongs in one reviewed file per service type, not scattered across Helm values and application code.
The playbook
1. Inventory what you have
List how each service configures its SDK today: environment variables, code, agent flags. You will usually find a few patterns that cover most services, and a long tail of one-offs.
2. Check language support
Support varies by language and by feature. The project tracks it in the specification compliance matrix and the configuration repository's language support status13. Start with the languages where support is mature in your stack.
3. Write a small set of standard files
Create a baseline per service type, such as web API, worker and batch job, covering resource attributes, exporters to your Collector gateway, batching, sampling and views. Keep secrets and endpoints as substitutions.
4. Ship the file with the platform, not the app
Mount it from a ConfigMap or bake it into base images, and set OTEL_CONFIG_FILE in your deployment templates. Teams inherit good defaults without copying settings.
5. Validate in CI
The model is defined by a JSON schema, so files can be validated before they ship3. Add the check to the same pipeline that enforces admission policies.
6. Migrate service by service
Run the declarative file alongside existing settings in a non-production environment, compare the telemetry produced, then switch. Pay attention to resource attributes and sampling, where small differences change dashboards and costs.
7. Plan for deprecations
The project intends to deprecate environment variables that don't interoperate well with declarative configuration, while making clear that deprecation is not deletion16. Moving now avoids a rushed migration later.
Where to be careful
- Precedence. Understand how the file interacts with remaining environment variables in each language before assuming one wins.
- Instrumentation configuration. The API for configuring instrumentation through the model was out of scope for the initial stabilisation1; check what your language supports.
- Runtime changes. Dynamic configuration, changing telemetry without a restart, is still being designed1.
- Stability is per language. A stable schema doesn't mean every SDK implementation is stable yet; follow the same approach as stable by default.
How I can help
I design observability platforms where telemetry is configured once, centrally and consistently, from SDK to Collector to backend. As a fractional CTO I can own that roadmap. Or analyse your challenge and bring the result to a call.
- 1Declarative configuration is stable!OpenTelemetry blog · 5 Mar 2026
- 2Configuration (OpenTelemetry specification)OpenTelemetry
- 3opentelemetry-configurationOpenTelemetry, GitHub
- 4The voyage of a small environment variableOpenTelemetry blog · 14 Jul 2026
- 5Declarative configuration (SDK configuration docs)OpenTelemetry documentation
- 6Deprecate environment variables which don't interoperate with declarative config (tracking issue)OpenTelemetry specification, GitHub