/blog/opentelemetry-best-practices
service naming + cardinality + sampling
free plan / 1 gb-mo
telemtra.io
// practices

OpenTelemetry best practices
for production.

A short list of the practices that separate a healthy OpenTelemetry deployment from one that becomes hard to query, expensive to store, and unreliable to debug. Most of these are not in the spec; they come from operating OTel pipelines for real services.

1. Use stable service names

service.name is the most important attribute in your stack. It is the key to every dashboard, every alert, every Service Map node. Pick a name, set it once via OTEL_SERVICE_NAME, and never put random suffixes (pod hashes, replica numbers, deploy timestamps) in it. Random suffixes are the most common cause of "why is my Service Map a hairball" complaints.

2. Always set deployment.environment

Without an environment, production and staging end up in the same dashboards. deployment.environment belongs in OTEL_RESOURCE_ATTRIBUTES and should be one of a small enum: production, staging, preview, development. Saved views in Telemtra scope by this attribute.

3. Use the W3C tracecontext propagator

If you have any choice in propagators, use tracecontext. It is the default in current OTel SDKs and what every modern backend expects. Mixing propagators across services is the leading cause of "my traces are broken across this boundary."

4. Keep span attributes enumerable

Span attribute values should come from a bounded set. http.status_code is fine (a few hundred values). user.id is not (a million values, unbounded growth). High-cardinality attributes inflate indexes, slow queries, and burn quota. Put unbounded values in span events or in correlated log records, not on the span itself.

5. Instrument boundaries, then business operations

Auto-instrumentation handles the boundaries: incoming HTTP, outgoing HTTP, DB queries, queue publishes. That is the first 80% of trace value. The next 20% is manual spans around business operations worth naming — checkout, fraud check, expensive report. Do not over-instrument with one span per function; the resulting waterfall is unreadable.

6. Run a Collector. Always.

App-direct OTLP works, but a Collector buys you batching, retries, backoff, a single egress connection, and a stable place to add filtering, sampling, and attribute enrichment. The cost is one container; the benefit is operational sanity.

receivers:
  otlp:
    protocols:
      http:
        endpoint: 0.0.0.0:4318

processors:
  memory_limiter:
    check_interval: 1s
    limit_mib: 512
  batch:
    timeout: 5s
    send_batch_size: 1024

exporters:
  otlphttp/telemtra:
    endpoint: https://ingest.telemtra.io
    headers:
      x-api-key: ${env:TELEMTRA_API_KEY}

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlphttp/telemtra]

7. Filter known noise before it leaves the cluster

Health checks, readiness probes, static asset requests, internal cron polls — none of these belong in your trace store. Drop them in the Collector with a filter processor matching span name or URL. The cheapest spans are the ones you never store.

8. Sample with intent, not by guess

If you sample, use tail sampling so every error and slow trace is kept. Head sampling at a flat percentage will silently drop the traces you most want to look at. See OpenTelemetry sampling strategies for the full pattern.

9. Correlate logs with trace IDs

OpenTelemetry's logging APIs attach trace and span IDs to every log emitted inside an active span. Use them: the difference between "guess which logs go with this trace" and "click span → see the exact log lines" is enormous during a real incident.

10. Use semantic conventions

If a name exists in the OpenTelemetry semantic conventions (http.request.method, db.system.name, messaging.destination.name), use it. Custom attribute names work, but you lose the ability to query across services consistently.

11. Apply ingest-time cleanup for what survives

Some noise can only be recognized after parsing — masked PII, oversized debug bodies, log lines that should be severity-rewritten. Use Data Shaper on the Telemtra side as the last cleanup layer.

12. Watch quota at 80% and 90%, not at 100%

Telemtra warns at 80% and 90% of monthly ingest. Treat the 80% warning as a real signal to investigate top fields and patterns; treat 90% as the deadline to act. Do not wait for 100% hard stop to look at usage.

13. Document the service name → owner map

OpenTelemetry does not enforce ownership. Maintain a list (in your service catalog, in CODEOWNERS, in a wiki) that maps every service name in Telemtra to a team and an on-call. Without it, alerts route to the void.

See What is OpenTelemetry? for the basics, the Collector quickstart for a working pipeline, and how to avoid noisy observability bills for cost specifics. Start a Telemtra workspace to apply these on real telemetry.

Further reading