The Datadog Bill, Decoded
What you’re charged for, where Datadog’s own levers stop, and how to keep Datadog while sending it less. A guide to custom metrics, indexed logs, indexed spans, and the repetition you’re paying index prices for.
The short answer: Datadog does not have one price. It has three volume meters (distinct custom-metric series, indexed log events, indexed spans), and each one grows faster than your traffic because each one counts something other than traffic. A large share of what those meters count is repetition: the same log line thirty thousand times, the same metric split by a tag nobody queries, the same healthy trace indexed all day. Datadog’s own levers (Metrics without Limits, exclusion filters, retention filters, archives) are worth turning on first, and this guide tells you where each one stops. What’s left after that is repetition, and the cheapest way to stop paying for it is not a better rule but a different step: read every record before Datadog does, collapse the copies into patterns with counts, and index the pattern. That is Telemetry Distillation. It runs beside your Agent as a second reader, not in place of it. Datadog stays. It just gets less.
Key takeaways
- Datadog bills on three volume axes: custom metrics by distinct tag combination (one combination is one billable series), logs by GB ingested and then again by million events indexed and retained, APM by GB ingested and then again by million spans indexed. The second charge is the one that moves.
- Custom-metric cardinality is the nonlinear axis. One unbounded tag on one busy metric multiplies series count between invoices, and the bill is the smaller problem; query timeouts during the incident are the larger one.
- Datadog’s native levers work by predicting what won’t matter: which tags to drop, which logs to exclude, which spans to retain. They are correct for the failures you already know about. Turn them on. Then notice what they can’t reach.
- Indexed repetition is the share of what Datadog indexes that is a copy of a pattern you already have. In the accounts we’ve looked at it is commonly the largest share of indexed log volume, and no exclusion filter can name it in advance.
- Telemetry Distillation reads the actual content of every log line, not just its status code or level: sentiment, patterns, anomalies, and severity. It collapses repetition into patterns with counts, baselines each service, and surfaces what’s new. Nothing sampled or filtered. It runs beside the Datadog Agent as a second reader of the same sources: a read-only key for CloudWatch, a one-command agent for Kubernetes, one added
otlphttpexporter if you already run a collector. Staging first. The Agent and Datadog are untouched.
What is indexed repetition?
Indexed repetition is telemetry that Datadog indexed, retained, or counted as a distinct series even though an identical pattern was already indexed: the ten-thousandth copy of a retry line, the healthy trace that looks like the last healthy trace, the metric series that differs from its neighbor only by a request ID. It is billed at the index rate, not the ingest rate, and it carries no information the first copy didn’t. In the Datadog accounts we’ve worked with it is commonly the largest share of indexed log volume, and it is invisible in the invoice because the invoice reports totals, not patterns.
The term is deliberate. “Volume” is what the invoice shows. “Repetition” is what the volume is made of. Datadog’s pricing pages, the FinOps dashboards, and most cost-reduction advice treat volume as the unit: send fewer GB, index fewer events, drop more tags. That framing leads to the wrong tools, because the tools that cut volume by rule (exclusion filters, sampling, tag drops) have to guess which volume is safe to lose, and the guess is made once, at configuration time, about data that hasn’t arrived yet. Repetition is different. You don’t have to guess whether the thirty-thousandth copy of a line matters. It doesn’t. The first copy, its count, and its time range are the record. The other 29,999 are the bill.
Two people read this guide for different reasons. The engineering manager or FinOps owner wants the number: how much of the indexed volume is repetition, in the invoice’s own units. The platform engineer who configures the Datadog Agent wants to know what changes in their pipeline and what doesn’t. The answer to the second question is the reason the first is worth asking: nothing in the Agent changes, and Datadog stays exactly where it is.
What am I actually billed for?
Datadog bills each signal on two axes, ingestion and indexing, and bills custom metrics on a third that has nothing to do with traffic: the count of distinct tag combinations. Misreading the split is the most common cause of a surprise invoice, and the same shape repeats across logs, APM, and metrics, so it is worth being precise about it once.
| Line item | Billing unit | What actually drives it | Grows with traffic? | Datadog’s native lever |
|---|---|---|---|---|
| Custom metrics | Distinct time series per month, over the per-host allotment. One unique tag combination is one series. | Tag cardinality. api.request.count tagged with env, region, user_id, container_id is not one metric; it is the product of every value of every tag. |
No. Multiplicative. A new unbounded tag multiplies series overnight. | Metrics without Limits: choose which tags are queryable; unqueried tags don’t count toward indexed series. |
| Log ingestion | GB ingested. | Raw volume: every line every service emits, including the ones excluded before indexing. | Roughly linear | Exclusion filters at the index (still ingested). Upstream reduction at the Agent or a collector (not ingested). |
| Log indexing & retention | Million events indexed, priced by retention tier (3, 7, 15, 30 days). | Everything that passes the exclusion filters, times how long you keep it. Duplicated pipelines (Datadog and a SIEM both indexing the same logs) double it. | Jumps, doesn’t creep A deploy that enables debug logging or a retry loop moves it in an hour. | Index exclusion filters, per-index daily quotas, archives to S3 with rehydration. |
| APM ingestion | GB of spans ingested. | Every span from every instrumented service, before any retention decision. | Roughly linear | Head-based sampling at the tracer or Agent (decides before seeing the trace). |
| APM indexing | Million indexed spans, 15-day retention. | Spans matched by retention filters plus the default intelligent retention. Most indexed spans are healthy, routine traffic. | Depends on filters Broad retention filters index everything; tight ones lose the baseline. | Retention filters (keep errors, keep slow, keep a percentage of the rest). Tail-based sampling in a collector. |
Two rows deserve a closer look. The first is custom metrics, because it is the only line that doesn’t follow traffic. Ingest and index grow roughly with request volume. Series count grows with the product of attribute values, so one engineer adding pod_name to a metric during a rolling deploy can multiply the series count by the number of pods that existed that day, and the invoice arrives a month later with no deploy to point at. The bill is the visible damage. The invisible damage is dashboards that time out during exactly the incident the metric was meant to explain, which is the cardinality explosion incident in Datadog’s clothing.
The second is log indexing, because it is where most of the surprise lives. Datadog separated ingestion from indexing so you could ingest everything cheaply and index selectively. In practice, exclusion filters are written once against yesterday’s noise, so today’s new noise (a new service, a new debug line, a new retry storm) sails through and gets indexed at the full rate. The Why did my Datadog log bill spike? card walks the diagnosis; the short version is that log bills almost never creep. They jump, and the jump is a pattern.
Put the three lines side by side and the shape is the same. A retry storm is thirty thousand indexed log events and one fact. A healthy checkout path traced ten thousand times a minute is ten thousand indexed spans and one shape. A metric split by request ID is a million series and one number per second. In every case Datadog is charging index prices for repetition, and in every case the native lever for that line item works by asking you to predict, in advance, which repetition you won’t need.
Where does each Datadog line item go wrong, and where does the native fix stop?
Each of Datadog’s three meters has a failure pattern, a native lever that addresses it, and a ceiling the lever can’t get past. The ceiling is the same each time: the lever needs you to know in advance what won’t matter. What follows is the four-part structure from the Guide to Controlling Datadog Costs, rewritten around that ceiling.
Custom metrics: one tag makes a metric explode
In Datadog, a custom metric is not a name. It is a name times every combination of tag values that has ever reported. api.request.count with env (3 values), region (6), and status (5) is 90 series. Add user_id and it is 90 times your active-user count. Each series is billed monthly over the allotment your hosts include, and each one has to be scanned when someone opens the dashboard.
What the native lever does. Metrics without Limits separates the tags you ingest from the tags you can query. Tags you don’t allowlist for querying don’t count toward indexed series. It is the right first move for any metric that has grown a volatile tag, and it costs nothing but the dashboards that were using that tag.
Where it stops. It is a per-metric allowlist, so someone has to know which metric exploded and which tag did it. Datadog’s custom-metrics governance pages help you find the top offenders after the fact. They can’t tell you that a tag added in today’s deploy is about to become tomorrow’s top offender, and the dimension you drop is usually the one that would have answered “which tenant” during the next incident. The Why are my Datadog custom metrics so expensive? card has the arithmetic; the high-cardinality post has the log side of the same problem.
APM: you’re indexing the traces that were fine
Datadog APM ingests every span and indexes the subset your retention filters match, plus an intelligent-retention slice. The default posture on most accounts indexes a broad sample of routine, healthy traffic, because that is the safe setting when you don’t yet know what you’ll need. Meanwhile head-based sampling at the tracer, which decides before the request finishes, is dropping traces before anyone knows they contain an error.
What the native lever does. Retention filters let you keep every error, every trace over a latency threshold, and a percentage of the rest. That converts a broad index into a targeted one and cuts the indexed-span line accordingly.
Where it stops. Retention filters are policies, and policies describe the failures you’ve already classified. The trace that succeeded in 400ms three minutes before the same code path started failing didn’t match a policy, so it’s gone, and it was the one that showed what normal looked like. Tail-based sampling in a collector improves on head-based by deciding after the trace completes, and it is still a policy. The Indexed vs. ingested spans card covers the mechanics.
Logs: ingest is cheap, index is where the money goes, and two teams are indexing the same lines
Logs are the largest and least controlled source of Datadog spend because every line can carry dynamic fields (request IDs, session tokens, payload fragments), because volume jumps rather than creeps, and because the security team is often duplicating the same stream into a SIEM. Same logs, indexed twice, paid for twice.
What the native lever does. Exclusion filters stop matched logs from being indexed (they are still ingested). Per-index daily quotas cap the damage from a spike. Archives send everything to S3 where it can be rehydrated into Log Explorer for a bounded window when you need it. Archiving is the one reduction in this guide that is reversible, and you should be doing it regardless.
Where it stops. Exclusion filters are written against noise you’ve already seen. The retry storm from a service that shipped this morning matches no filter and gets indexed at full rate until someone notices the usage graph. And a filter that excludes a whole service or severity is also excluding the INFO line that says something slightly different from yesterday’s INFO lines, which is where new failures first appear. The log bill spike card is the 30-minute diagnosis; the SIEM double-pay is a routing problem a collector solves in front of both destinations.
AI-SRE tools: garbage in, garbage out, at index prices
The fourth pillar isn’t a line item. It’s what the other three do to the tools you’re pointing at the data. AI-SRE and AIOps systems, Datadog’s own included, are only as good as the telemetry they read. Feed them thirty thousand copies of a retry line and they spend their context on the copies. Feed them a metric with a million series and root cause is a needle in a haystack you paid to build. The same repetition that inflates the bill degrades the answer.
Where the native levers stop. There isn’t one for this. Reducing volume by rule makes the haystack smaller but doesn’t change its composition; it is still raw records, still mostly copies. What an agent needs is the distilled form: the pattern, its count, its baseline, and what’s new against it. That is the input Möbius works from, and it is why the cost fix and the AI-readiness fix turn out to be the same step.
How do you send Datadog less without deciding in advance what to drop?
You send Datadog less by collapsing repetition before it reaches the index instead of selecting records by rule: read the actual content of every log line (its sentiment, its pattern, whether it’s anomalous, and its severity), group identical patterns into one entry with a count, baseline each service against itself, and flag what’s new against that baseline. That is content-based reduction rather than rule-based reduction, and it removes indexed repetition without anyone having to name it first. We call it Telemetry Distillation. (Not model distillation, which compresses a machine-learning model; this compresses the telemetry.) The OpenTelemetry Signal Loss guide makes the case from the collector side. This is the same method seen from the invoice.
The Agent path is not touched. A second reader (a CloudWatch pull, an in-cluster agent, or a collector exporter) takes the same sources beside it, Telemetry Distillation collapses the copies, and the first thing you get is the number: how much of what Datadog indexed was repetition.
| Datadog’s native levers | Rule-based collector reduction | Telemetry Distillation | |
|---|---|---|---|
| Decision made | In the Datadog UI, once, per metric / index / retention filter | In collector config, once, per processor | Continuously, by the content of each record |
| What it removes | Tags from the query allowlist; logs matching an exclusion; spans not matching retention | Records matching a policy (severity, sample, attribute) | Copies of repeated patterns; the pattern and count remain |
| What it keeps | What you allowlisted or retained | What you predicted would matter | One exemplar per pattern, plus anything new against baseline |
| The new failure | Indexed at full rate until someone writes a filter | Dropped first; no rule anticipated it | Surfaced first; it’s the pattern that doesn’t match |
| Where it runs | Inside Datadog, after ingestion (you paid ingest) | In the export path; changes what Datadog receives | Beside the Agent, reading the same sources; Datadog receives what it did |
| Changes the Agent? | No | Yes, if the collector is in front of it | No |
| Reversible | Archives yes; filters no | No | No for the copies; the pattern, count, and exemplar are the record |
Telemetry Distillation is a different kind of reduction for four reasons that matter to the bill.
It reads the content, not the metadata. Every native lever keys on something outside the message: a tag name, a severity level, a status code, a percentage. Continuous Telemetry Distillation reads the actual content of every log line, not just its status code, and scores it on four things: sentiment (a line that reads like a failure is treated as one, whatever level someone gave it), pattern (has this shape been seen before, and how often), anomaly (is it unusual for this service), and severity (the level, weighed against the other three rather than trusted alone). Signal and noise are separated by what the record says, which is the only place the distinction lives. It’s also why an INFO line that says something new survives while a thousand ERROR lines that say the same thing collapse to one.
It collapses, it doesn’t select. Thirty thousand identical retry lines become one pattern with a count of thirty thousand and a time range. Nothing is sampled. Nothing is filtered. Every record is read. The reduction is in repetition, not in coverage, which is what lets it produce a number Datadog’s usage pages can’t: the share of your indexed log volume that was copies.
It’s baselined per service. What is noise in checkout-api is not noise in auth-service. An exclusion filter is written once and applies everywhere. A baseline is learned per stream and moves with the service, so the new pattern in a quiet service is loud and the routine pattern in a loud service is quiet.
It sits beside Datadog, not in front of it. This is the property that makes the rest safe to try. The Agent keeps shipping to Datadog. Distillation reads the same sources a second time. Nothing in the existing path changes, so the governance conversation is “can a second reader see staging’s logs,” not “can we re-plumb production observability.”
What if you only run the Datadog Agent?
You don’t need a collector, and you don’t need to touch the Agent, because Telemetry Distillation doesn’t read from the Agent. It reads from the same places the Agent reads. Dstl8 calls each of those a source, and for a Datadog team the relevant ones are below, in the order of least to most installed. The honest constraint first: there is no way to tap the Agent’s own transport to Datadog. A second reader reads the sources, not the Agent.
| Where your logs are | The ask | What gets installed | Touches the Agent? |
|---|---|---|---|
| AWS (Lambda, ECS, EC2, EKS via CloudWatch log groups) | Create a read-only IAM user with CloudWatchLogsReadOnlyAccess, paste the key into a CloudWatch source. Dstl8 pulls. | Nothing | No |
| Kubernetes | Add a Kubernetes source, run the prefilled install.sh. Helm installs a DaemonSet that reads the same container logs the Agent tails, plus a cluster component for events and topology. | The ControlTheory agent, in its own namespace | No |
| Google Cloud | Add a Google Cloud source with read access to Cloud Logging. Dstl8 pulls. | Nothing | No |
| Already sending OpenTelemetry into Datadog | Add one otlphttp exporter to the collector you have, pointed at an OTLP source. The Datadog exporter stays. | Nothing new | No |
| Want one routing point for Datadog, a SIEM, S3, and Dstl8 | Put an OpenTelemetry Collector with the Datadog receiver in the Agent’s path and point the Agent at it. This is the step that eventually ends the SIEM double-pay. | A collector tier | Yes, later |
Three things to notice about the first four rows. The Agent’s configuration is not part of any of them. Each is a same-day setup: a source goes from Pending to Healthy within minutes of the first logs arriving, and streams are detected and named by what emitted them (a Lambda function, a Deployment, a DaemonSet). And a second reader costs a second read: on Kubernetes that’s two tailers on the same files and a little CPU per node, on CloudWatch it’s read API calls against the log groups. On staging, or on one production account, that’s fine, and it’s the price of not touching the Agent.
Start with one source on staging, or the one AWS account whose Log Management line you understand best. The output is a per-stream repetition share that maps to that account’s indexed events. When you later want a single place to route from, the last row is the same collector tier the Signal Loss guide describes, and by then you know which streams are worth routing.
If you already run a collector
For the fourth row, the whole change is one exporter beside the one you have:
exporters:
datadog:
api:
key: ${env:DD_API_KEY} # your existing Datadog exporter, unchanged
otlphttp/dstl8:
endpoint: https://<org_id>.app.dstl8.ai/src-<id>
headers:
Authorization: "Bearer <your-token>"
service:
pipelines:
logs:
receivers: [otlp, filelog]
processors: [k8sattributes, batch]
exporters: [datadog, otlphttp/dstl8] # add dstl8, keep Datadog
Datadog receives exactly what it received before. Dstl8 receives a copy. If you want to see the patterns before any exporter is added, dstl8 tap runs the same distillation against a local stream, and Gonzo shows them in a terminal with nothing leaving the machine.
Dstl8 is Telemetry Distillation for the sources your Agent already reads
Dstl8 reads your logs from the sources the Agent already reads (CloudWatch, Kubernetes, Google Cloud, or any OpenTelemetry exporter), beside the Datadog Agent and without changing it. It reads the actual content of every log line for sentiment, patterns, anomalies, and severity, collapses repetition into named patterns with counts, baselines each service against itself, and surfaces what’s new. Möbius, the agent inside Dstl8, correlates a new pattern to the deploy, config rollout, or upstream change that preceded it, with the evidence cited. The first output, from one staging source, is a number in your Log Management line’s units: how much of what you index is repetition. The argument in this guide covers all three meters; the product output today is logs. What you do with the number in Datadog (add an exclusion, tighten a quota, archive more) is your call, and Datadog stays where it is.
Book a 20-minute bill session Add a source (docs)Should you leave Datadog?
No, or at least not because of the bill. Here is the part most cost-reduction content skips: the vendors ranking for “reduce Datadog costs” mostly want you to replace it, and replacing an observability platform is a year of work that trades a known bill for an unknown one. You chose Datadog for reasons that haven’t changed. The dashboards, the alerts, the muscle memory of the on-call rotation are worth more than the delta on the invoice. Keep it.
Also keep the native levers, and turn them on before you talk to anyone, us included. Metrics without Limits on any metric that grew a volatile tag. Exclusion filters for health checks and load-balancer noise. Retention filters that keep errors and slow traces. Archives to S3 for everything, because rehydration is the only reversible decision in this guide. A team that has done those four things has usually cut the bill meaningfully, and the guide so far tells you exactly where each one stops.
What this guide argues against is narrower: treating those levers as the whole answer, because each one works by predicting which data won’t matter, and the data they’re worst at predicting is the repetition that makes up most of the index. Severity-based exclusions. Dropping the tag that identifies the tenant. Broad probabilistic retention. Those are the rules that save the most money and lose the most signal, and they are the ones Telemetry Distillation replaces, by collapsing the copies instead of guessing which ones are safe to drop.
The practical posture: keep Datadog, keep the levers you can defend as requirements, remove the ones you wrote to hit a number, and let content-based reduction hit the number instead. Then measure it, on staging, so “this much of our indexed log volume is repetition” is a figure in your invoice’s units and not a vendor’s claim.
What to change in Datadog once you have the number
Nothing, at first. Run both for a week on one source and let the pattern list tell you where the repetition is. Then work down this list, in order of how easily each step reverses.
Exclusion filters, written from the pattern list. The top repeated patterns that carry no information (health checks, retry chatter, startup noise) become exclusion filters on the index they land in. Still ingested, no longer indexed, so it moves the expensive line. Fully reversible in the Datadog UI. Before excluding anything, check which log-based monitors and dashboards query that index; excluded logs don’t feed them.
Archive-only for streams nobody queries. For the debug and INFO streams where the distilled patterns are now the surface people actually read, route them ingest → archive with no index. Rehydration keeps them recoverable for a bounded window. This is the S3 tiering the eBook described, done with Datadog’s own feature.
Per-index daily quotas as the backstop. A new pattern won’t match an old exclusion filter. A quota caps the damage from the next spike until someone writes the filter, and the distilled stream is where you’ll see the new pattern first.
Only after the collector tier: stop sending. Once a collector sits in the Agent’s path, streams that have moved to archive-only can stop going to Datadog at all, which also moves the ingest line, and the SIEM copy can be routed from the same place, which ends the double-pay. This is the step that changes the Agent’s configuration, so it is last.
Don’t touch: the error and warning indexes on-call depends on, anything a monitor references, and retention required for compliance. And since Dstl8 distills logs today, custom metrics and APM stay entirely on Datadog’s native levers from the pillars above.
Where do you go when you’re looking at one of these line items right now?
Every line item and every lever in this guide has a working page behind it: the arithmetic, the configuration, and the failure modes we’ve hit. In the order you’d actually read them.
Cardinality
Datadog and the collector
Reducing what you send, and what it costs
The method, from the other side
References
- Datadog, Custom metrics billing: billable series as distinct tag combinations, per-host allotments, and overage.
- Datadog, Metrics without Limits: separating ingested tags from queryable tags.
- Datadog, Log Management billing, Indexes and exclusion filters, and Archives.
- Datadog, APM billing and the trace pipeline: ingested vs. indexed spans and retention filters.
- The New Stack, Datadog’s $65M bill and why developers should care.
- ControlTheory, A Guide to Controlling Datadog Costs (eBook): the four-pillar structure this guide rewrites, and the “80% of spend from 7% of data” observation.
- ControlTheory, The Engineer’s Guide to OpenTelemetry Signal Loss: the reduction toolkit table and the Telemetry Distillation definition.
Frequently asked questions
What does Datadog actually bill for?
Three volume meters. Custom metrics are billed by distinct time series per month over your per-host allotment, where one unique tag combination is one series. Logs are billed once by GB ingested and again by million events indexed, priced by retention tier. APM is billed once by GB of spans ingested and again by million spans indexed. The second charge on logs and APM, and the series count on metrics, are where surprise invoices come from.
What is indexed repetition?
The share of what Datadog indexed, retained, or counted as a distinct series that is a copy of a pattern already indexed: the ten-thousandth retry line, the healthy trace identical to the last one, the metric series that differs only by a request ID. It’s billed at index prices and carries no information the first copy didn’t. In the accounts we’ve worked with it is commonly the largest share of indexed log volume.
Isn’t Metrics without Limits enough for custom metric costs?
It’s the right first move. It lets you ingest a tag without paying to make it queryable, and it stops the bleeding on any metric you’ve identified. Where it stops: it’s a per-metric allowlist, so it can only fix explosions you’ve already found, and the tag you drop is often the one that would have told you which tenant or pod was the problem during the next incident.
Do I have to replace the Datadog Agent to use Telemetry Distillation?
No. Distillation doesn’t read from the Agent; it reads the same sources the Agent reads. On AWS that’s a read-only key against your CloudWatch log groups, nothing installed. On Kubernetes it’s a one-command agent in its own namespace. If you already send OpenTelemetry into Datadog, it’s one added exporter on the collector you have. The Agent keeps shipping to Datadog unchanged.
Is this a Datadog replacement?
No. Datadog stays as your dashboards, alerts, and on-call surface. Telemetry Distillation runs beside it, tells you how much of what you index is repetition, and gives you the distilled patterns and what’s new. What you change in Datadog with that information (a retention filter, an exclusion, fewer allowlisted tags) is your decision.
What does “reads the content” mean, as opposed to filtering by severity?
An exclusion filter or a severity threshold looks at metadata: the level, the status code, the source. Continuous Telemetry Distillation reads the text of every log line and scores it on sentiment (does it read like a failure), pattern (has this shape been seen, how often), anomaly (is it unusual for this service), and severity (the level, weighed with the rest). A retry line logged at ERROR ten thousand times collapses to one pattern with a count. An INFO line that reads like a failure and hasn’t been seen before is surfaced. Neither outcome is available to a rule that only sees the level.
How do I find out what the number is for my account?
Add one source on staging (a CloudWatch account, a cluster, or an exporter on an existing collector). Within a day the output is the share of that source’s log volume that was repetition, in indexed log events. Dstl8 distills logs today; the metrics and APM arguments in this guide are for you to apply with Datadog’s own levers. A 20-minute session walks the log number against your invoice.
A large share of what you index is copies. Find out how many, in your invoice’s units.
One source beside the Agent, on staging. Datadog untouched. Your indexed-log repetition number in a day, the patterns behind it, and what’s new, cited to the record.
Book a 20-minute bill session Add a sourcebrew install control-theory/dstl8/dstl8 && dstl8 setupWant to see the patterns in one log stream first, without anything leaving your machine? Gonzo reads log and OTLP streams in the terminal, free and open source. When you want the number across an account or a cluster, Dstl8 is one source away.














