The bill that grows on its own#
Every quarter the same scene plays out in some Slack channel: someone shares the latest Datadog invoice and the thread fills up with disbelief, gallows humor and the classic "I told you so." If your bill has grown much faster than your infrastructure since you started, you're not an outlier.
The pattern is usually identical. You start with APM for a handful of services. Then you add logs, because correlating traces with log lines is useful. Then custom metrics creep in. Someone turns on RUM. And one day you open the bill and discover that observing your infrastructure costs an uncomfortable fraction of what the infrastructure itself costs.
This isn't an attack on Datadog. The product is genuinely good and its interface is still among the best on the market. The problem is structural: its pricing model charges per dimension (per host, per GB, per span, per metric series, per session), and that creates a growth tax that hits mid-sized teams hard. This guide explains where the spend comes from and how to use OpenTelemetry to regain control without losing visibility.
Documentation: Datadog · Pricing ↗
Why it spikes: the price multiplies, it doesn't add up#
Datadog doesn't charge a simple monthly fee. It bills each product and each dimension separately, and those dimensions all grow at once when you grow:
- Infrastructure: per monitored host.
- APM: per host with traces, plus the volume of ingested and indexed spans above what your plan includes.
- Logs: ingestion is billed per GB and, separately, indexing is billed per event based on the retention period. The same log can be paid for twice.
- Custom metrics: every unique combination of metric name and tag values counts as a billable metric. A histogram or a distribution generates several series per combination by default. That's why instrumenting with Prometheus or OpenTelemetry without controlling labels can produce thousands of series per service.
- RUM and other products: per session or by volume, depending on the product.
The result is a bill that grows super-linearly: adding a service doesn't just add a host, it adds spans, logs and, above all, new tag combinations. For most teams, APM and logs are the heaviest line items, and that observation defines the strategy: start where the spend is concentrated on your own bill. Prices change often, so always check the official pricing page and your account's usage details.
Documentation: Datadog · Pricing ↗ · Datadog · Custom metrics billing ↗ · Datadog · APM billing ↗ · Datadog · Log indexes and exclusion filters ↗
AI inflates telemetry#
There's a new variable breaking budgets: AI workloads. A single inference request can produce multi-step traces (context retrieval, model calls, tools, retries), high-cardinality attributes such as model or prompt identifiers, token counts worth tracking for cost and new evaluation metrics.
Each of those is one more dimension your observability platform can charge you for: more spans per request, more series for every new tag, more GB of logs containing prompts and responses. If you add LLM monitoring without first deciding which attributes you actually need and at what sampling rate, the bill will show it quickly.
The rule that applies here is the same as in the rest of this guide: if your observability costs more than the value of the decisions it enables, something is broken. Define which questions you want to answer about your AI workloads and collect only the telemetry that answers them.
Documentation: Datadog · Custom metrics billing ↗ · OpenTelemetry · Sampling ↗
The way out isn't dropping Datadog: it's a hybrid model#
Here's the nuance most Slack threads miss: the goal isn't to migrate everything to another tool in one go. The goal is to stop being held hostage by a pricing model that punishes you for growing.
The move that works is a hybrid model. You keep Datadog for what you actually get value from (typically the APM experience, dashboards and alerts on critical flows) and move low-value volume to cheaper backends, such as Grafana Loki for logs, Grafana Tempo or Jaeger for traces, and Grafana Mimir or VictoriaMetrics for metrics.
The piece that makes it possible is OpenTelemetry. It's an open, vendor-neutral standard for generating, collecting and exporting traces, metrics and logs. You instrument once with its SDKs and its OTLP protocol, and the OpenTelemetry Collector then decides where each signal goes. Changing destinations means changing the Collector configuration, not the application code.
Logs are usually the first thing to move, for two reasons: they tend to be among the most expensive line items and, when emitted via OpenTelemetry, they're the easiest to reroute. Loki accepts OTLP natively, so pointing an exporter at its endpoint is enough. Keep the trace_id as a log field so you can correlate logs with traces.
Documentation: OpenTelemetry · What is OpenTelemetry? ↗ · OpenTelemetry · Collector configuration ↗ · Grafana Loki · Ingesting logs with OpenTelemetry ↗
A Collector that decides where each signal goes#
The following example shows an OpenTelemetry Collector (contrib distribution) that sends all traces to Tempo, only a sample of production traces to Datadog, application metrics to Mimir and logs, minus DEBUG, to Loki.
receivers:
otlp:
protocols:
grpc: { endpoint: 0.0.0.0:4317 }
http: { endpoint: 0.0.0.0:4318 }
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 80
spike_limit_percentage: 20
batch: {}
# Don't pay Datadog for staging spans (they still go to Tempo)
filter/no-staging:
error_mode: ignore
trace_conditions:
- resource.attributes["deployment.environment.name"] == "staging"
# Send only a sample of production spans to Datadog
probabilistic_sampler:
sampling_percentage: 20
# Drop DEBUG logs before sending them to any destination
filter/no-debug:
error_mode: ignore
log_conditions:
- log.severity_number < SEVERITY_NUMBER_INFO
connectors:
# Computes APM metrics (hits, errors, latency) from 100% of traces
datadog/connector: {}
exporters:
datadog:
api:
site: datadoghq.com
key: ${env:DD_API_KEY}
otlp/tempo:
endpoint: tempo:4317
tls: { insecure: true }
otlphttp/loki:
endpoint: http://loki:3100/otlp
otlphttp/mimir:
endpoint: http://mimir:8080/otlp
service:
pipelines:
traces/all: # all traces, unsampled, to Tempo
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlp/tempo]
traces/datadog-in: # production into the connector (no sampling)
receivers: [otlp]
processors: [memory_limiter, filter/no-staging]
exporters: [datadog/connector]
traces/datadog-out: # sample out to Datadog
receivers: [datadog/connector]
processors: [probabilistic_sampler]
exporters: [datadog]
metrics/apm-stats:
receivers: [datadog/connector]
exporters: [datadog]
metrics: # application metrics to Mimir
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [otlphttp/mimir]
logs:
receivers: [otlp]
processors: [memory_limiter, filter/no-debug, batch]
exporters: [otlphttp/loki]Three details make the difference between saving money and breaking your observability:
- Compute APM metrics before sampling. If you sample traces before Datadog sees them, APM request rates, error rates and latencies are calculated on a fraction of the traffic. The Datadog Connector solves this: it receives 100% of the traces, computes those stats and only then forwards the sample.
- Filter on standard resource attributes. The current semantic convention is deployment.environment.name; if your services still emit deployment.environment, adjust the condition.
- Protect the Collector itself. The memory_limiter should come first in every pipeline so that a telemetry spike doesn't take down the Collector.
Probabilistic sampling is simple, but it can't tell interesting traces apart. If you always need to keep traces with errors or the slowest ones, use tail sampling, which decides once the trace is complete; the trade-off is that all spans of a trace must reach the same Collector instance.
Documentation: OpenTelemetry · Collector configuration ↗ · Datadog · OpenTelemetry Collector and Datadog Exporter ↗ · OpenTelemetry Collector Contrib · Datadog Connector ↗ · OpenTelemetry Collector Contrib · Filter processor ↗ · OpenTelemetry Collector Contrib · Tail sampling processor ↗ · OpenTelemetry · Sampling ↗ · Grafana Tempo · Documentation ↗ · Grafana Mimir · Configure the OpenTelemetry Collector ↗
Action plan: what to move and in what order#
Don't migrate out of enthusiasm; migrate for return. Tackle high-cost, low-effort items first, and leave for last whatever takes the most work or where the expensive tool genuinely shines.
- Map your billable dimensions. Open your Datadog account's usage details and classify every line: hosts, ingested and indexed spans, GB of ingested logs, indexed events, custom metrics, RUM sessions. Identify which ones are growing faster than your infrastructure.
- Pull the levers that don't require migrating first. Exclusion filters on log indexes, APM ingestion controls and Metrics without Limits to decide which tags get indexed can cut spend without moving anything.
- Divert low-priority logs. Debug logs, health checks and development noise don't need to be indexed in Datadog. Send them to Loki, keeping the trace_id for correlation.
- Control metric cardinality. Every high-cardinality label (user IDs, request IDs, full URLs) multiplies the series. Drop it in the Collector or route those metrics to Mimir or VictoriaMetrics.
- Sample traces. You don't need 100% of spans to understand a service's health, as long as APM metrics are computed before sampling.
- Keep critical traces in Datadog until the alternative is validated. Leave payment flows and core services in Datadog while you confirm that Tempo or Jaeger covers the rest with the experience your team needs.
Starting with logs and cardinality usually recovers most of the savings with the least risk, and often nobody notices a difference in the dashboards.
Documentation: Datadog · Usage details (Plan and Usage) ↗ · Datadog · Log indexes and exclusion filters ↗ · Datadog · APM ingestion controls ↗ · Datadog · Metrics without Limits ↗ · VictoriaMetrics · OpenTelemetry integration ↗
All-in on Datadog vs. a hybrid OpenTelemetry stack#
| Aspect | All-in on Datadog | Hybrid stack with OpenTelemetry |
|---|---|---|
| Custom metrics | Billed per combination of name and tags; grows with cardinality | Low-value ones go to Mimir or VictoriaMetrics; you pay for storage and operations |
| Non-critical logs | Ingestion per GB plus indexing per event | Sent to Loki; you pay for your own storage and compute or for a managed service |
| Development and staging traces | Spans billed like any other | Go to Tempo; Datadog receives only sampled production traffic |
| Trace-log correlation | Native in the Datadog UI | Via trace_id; requires instrumentation discipline |
| Operational complexity | Low: a single vendor | Medium: at least the Collector and one more backend to run |
The open stack isn't free: it shifts spend from licenses to infrastructure and engineering hours. The right decision depends on how much you pay today for low-value volume and whether your team can operate those components, or pay for their managed versions.
Documentation: Datadog · Custom metrics billing ↗ · Grafana Loki · Ingesting logs with OpenTelemetry ↗ · Grafana Tempo · Documentation ↗ · Grafana Mimir · Configure the OpenTelemetry Collector ↗
When staying on Datadog makes sense#
To be fair: there are cases where a high bill is justified. If you're a large organization with complex compliance requirements and dozens of integrations that a small team doesn't want to operate, paying for a polished, unified platform makes perfect sense. Running your own observability stack is real, ongoing engineering work.
Where the math changes is the mid-market: a mid-sized team with a few dozen microservices on Kubernetes rarely needs to pay full price for every debug log, every staging span and every tag combination. In that case, the open ecosystem built on OpenTelemetry is production-ready, and the question stops being "can I?" and becomes "what do I move first?"
Documentation: OpenTelemetry · What is OpenTelemetry? ↗
The one-line summary#
Instrument with OpenTelemetry so you're not tied to any vendor. Use Datadog's levers that don't require migrating first, move low-value logs, control cardinality and sampling in the Collector, and keep in Datadog only what you truly can't replicate. The goal isn't saving for its own sake: it's regaining control of a bill that currently grows on its own.
Sources and scope
Documentation checked on September 25, 2026. Examples and decision criteria are editorial proposals; adapt them to your application's contract and validate them in an authorized test environment.
- Datadog · Pricing ↗
- Datadog · Custom metrics billing ↗
- Datadog · APM billing ↗
- Datadog · Log indexes and exclusion filters ↗
- OpenTelemetry · Sampling ↗
- OpenTelemetry · What is OpenTelemetry? ↗
- OpenTelemetry · Collector configuration ↗
- Grafana Loki · Ingesting logs with OpenTelemetry ↗
- Datadog · OpenTelemetry Collector and Datadog Exporter ↗
- OpenTelemetry Collector Contrib · Datadog Connector ↗
- OpenTelemetry Collector Contrib · Filter processor ↗
- OpenTelemetry Collector Contrib · Tail sampling processor ↗
- Grafana Tempo · Documentation ↗
- Grafana Mimir · Configure the OpenTelemetry Collector ↗
- Datadog · Usage details (Plan and Usage) ↗
- Datadog · APM ingestion controls ↗
- Datadog · Metrics without Limits ↗
- VictoriaMetrics · OpenTelemetry integration ↗
Compare cloud options
Review pricing, limits, conditions and sources for each option (in Spanish).
Open comparison