How to Reduce Datadog Costs Without Losing Coverage

The first time a Datadog invoice made someone at our shop physically wince, it was custom metrics. Not hosts, not APM. A single service was emitting a counter tagged with user_id, and that one tag had quietly minted 400,000 metric series. Nobody queried it. Nobody knew it existed until the overage line showed up.

That's the pattern with Datadog. The bill grows in places you aren't looking, and the fix is almost never "turn off monitoring." It's finding the three or four line items eating your budget and trimming the waste out of them. Below is the order we work in, prioritized by return, not by which knob is easiest to reach.

Before you touch anything: go to Usage & Cost > Usage and look at the top SKUs by spend. Then open the estimated usage graphs for the current period. You want the actual dollar ranking, because everyone's Datadog is shaped differently. Fix the biggest number first. Guessing is how you spend a week saving forty bucks.

1. Logs first, almost always #

Logs are where the money hides. The key idea is that Datadog charges you separately for ingestion (bytes shipped in) and indexing (logs kept searchable). Indexing is the expensive part. Most teams index everything by reflex, then pay to make debug-level noise searchable for fifteen days.

Start in Logs > Configuration > Indexes and look at your exclusion filters. An exclusion filter drops matching logs from the index (you stop paying to index them) while still letting you keep them as ingested data for metrics or archives. Here's a filter that keeps 100 percent of errors but samples successful health checks down to nothing:

code

Exclusion filter: drop-200-healthchecks
Query: status:info @http.status_code:200 @http.url_details.path:/health
Sample rate: 100% (drop all matches)

And one that keeps a representative slice of chatty info logs instead of all of them:

code

Exclusion filter: sample-info-logs
Query: status:info -service:payments
Sample rate: 95% (index 5% of matches)

Note the -service:payments. Cardinality of caution: never blanket-sample your money paths. Sample the boring services hard, keep the ones you actually page on.

Then lean on Logging Without Limits. Ingest everything cheaply, index selectively, and archive the raw stream to S3. When an incident needs the logs you didn't index, rehydrate the relevant time window from the archive on demand. You pay for search once, during the incident, instead of every day forever. For a lot of teams this single change cuts the log bill by half without losing a single byte of forensic coverage.

2. Custom metric cardinality #

This is the sneaky one. Custom metrics are billed per unique series, and a series is every unique combination of metric name plus tag values. Add a high-cardinality tag and you multiply your bill silently.

Find the offenders in Metrics > Summary. Sort by number of distinct metrics, and use the tag breakdown to see which tags are exploding the count. You're hunting for tags like user_id, request_id, pod_name, container_id, or full URLs. None of those belong on a metric.

Fix it two ways. Best case, drop the tag at the source in your instrumentation. When you can't redeploy quickly, use Metrics Without Limits to configure which tags are kept for querying:

code

Metric: web.requests.count
Tags to keep: service, env, endpoint_group, http.status_class
Tags dropped: user_id, request_id, session_id

That config keeps the metric useful (you can still slice by service and status class) while collapsing the series count from hundreds of thousands to a few hundred. The ingested tags still exist if you ever need to re-enable one, so this is a low-risk move you can make in the UI today.

3. APM span ingestion and indexing #

APM has the same ingest-versus-index split as logs, and the same fix. In APM > Setup & Configuration > Ingestion Control you set trace sampling. Ship enough traces to keep p99 latency and error rates honest, but you do not need 100 percent of every healthy request.

Set head-based sampling per service, then add retention filters so the interesting spans always survive: keep every error trace, keep every trace over your latency threshold, and sample the fast happy-path traces down to 10 or 20 percent. You keep full visibility into what breaks and stop indexing millions of identical 40ms successes. If you're weighing whether Datadog APM is even the right home for this, we compared the field in APM tools.

4. Infra hosts #

Host billing is usually already tuned, but idle waste creeps back in. Pull the host list sorted by last-seen and by CPU, and kill agents on boxes that are decommissioned but still reporting. You pay for a host whether it does anything or not.

For anything containerized, remember Datadog bills a certain number of containers per host in the base price and charges for the rest. Right-size which containers actually need the full agent versus agentless coverage. And audit your monitors: alerting on hosts that no longer exist keeps the meter running and pages nobody.

5. Synthetics and RUM #

Synthetics bill per test run. A browser test firing every minute from eight locations is 480 runs an hour, and half of those locations tell you nothing new. Drop to the two or three regions your users live in, and stretch intervals on non-critical journeys to every five or ten minutes. Keep the checkout flow tight; let the marketing page breathe.

RUM bills per session. Sample it. A 20 or 30 percent session sample gives you statistically sound performance data without paying to record every last visitor.

6. Commitments and the unused-SKU audit #

Last, the finance moves. Once your usage has settled after the trimming above, look at a committed-use contract. On-demand Datadog is priced to punish you; annual commitments routinely save 20 to 40 percent, and reserved custom-metric and log volumes drop the unit price further. Right-size the commit to your post-cleanup baseline, not your bloated peak, or you're prepaying for waste. The mechanics are worth understanding first in Datadog pricing.

Then walk the SKU list one more time and cancel what nobody uses. CI Visibility that one team enabled and abandoned. A Database Monitoring add-on on a retired cluster. Profiler on services no one profiles. These sit on the invoice for months because canceling them is nobody's job.

The call we'd make #

Attack logs and custom metrics first, because that's where eight out of ten overages live. Get ingest split from index, sample the noise, drop the cardinality tags, and only then negotiate a commit against your new, smaller baseline. Do it in that order and you'll knock 30 to 50 percent off the bill while keeping every alert that has ever actually woken you up. Chase the small SKUs first and you'll spend a week to save a rounding error. Follow the dollars, not the dashboards.