Adding one tag to one metric can multiply your Datadog bill overnight. StepChange documented the spike in December 2024 after a team running GKE Autopilot watched their bill jump 20x because a default prometheus.io/scrape: true annotation let Datadog's Prometheus integration ingest metrics from GKE-managed pods it should never have touched. The mechanism is predictable: Datadog bills by timeseries, and tag cardinality multiplies timeseries count before the invoice arrives.
What is a Datadog custom metric
Datadog treats any metric outside its 1,000+ integrations as a custom metric. Datadog's billing docs set the boundary directly: metrics that do not come from one of Datadog's more than 1,000 integrations count as custom metrics.
Datadog bills the timeseries, which combines the metric name with tag values. Datadog identifies each custom metric by the combination of metric name and tag values, including the host tag, and each unique combination is one timeseries. Ship checkout.latencytagged with service and endpoint across multiple regions, and every distinct combination of those values counts as a separate billable timeseries.
These submission paths count toward your quota:
- DogStatsD
- The HTTP API
- Custom Agent checks and PowerShell
- AWS Lambda
So do metrics you generate inside Datadog from logs, APM spans, RUM events, and live processes, covered in detail below.
How Datadog counts and bills custom metrics
Datadog bills custom metrics as a monthly average of distinct timeseries, with a per-host allotment included in each plan. The formula, from Datadog's billing docs: "Your monthly billable custom metrics usage is calculated by taking the total of all distinct custom metrics (also known as timeseries) for each hour in a given month, and dividing it by the number of hours in the month to compute a monthly average value." That is a simple arithmetic mean. Infrastructure hosts use a different method, the 99th-percentile high-water mark, and confusing the two leads to bad forecasts.
Plan allotments are pooled across your account, not enforced per host:
- Infrastructure Pro: The plan includes 100 ingested and 100 indexed custom metrics per host.
- Infrastructure Enterprise: The plan includes 200 ingested and 200 indexed custom metrics per host.
Beyond the allotment, the list rate is $5.00 per 100 indexed custom metrics per month, an effective $0.05 per timeseries per month. When you configure Metrics without Limits™, Datadog charges ingested custom metrics at $0.10 per 100 per month. Two caveats: real-time usage counters diverge from billable usage by 10-20% on average, and as of June 9, 2026 Datadog offers an opt-in Metric Name Pricing model that bills by metric name rather than timeseries count. Check which billing model applies to your account before planning optimization work, because the strategies differ.
The timeseries as the billing unit
One metric name can equal thousands of billed timeseries because the timeseries count is the product of every tag's unique values. A checkout.latency metric with 10 services across 50 endpoints in 4 regions can produce up to 2,000 billable timeseries. At list price, that single metric name costs up to $100 per month before you add a single new tag.
The multiplication also runs through metric type. A HISTOGRAM generates five timeseries per tag combination by default (avg, count, median, 95percentile, max), so the docs' own example, a request.Latency histogram with 4 tag combinations, bills as 20 custom metrics. A DISTRIBUTION with percentile aggregations enabled generates 10 timeseries per combination.
Tag cardinality and metric explosion
One unbounded tag turns a low-cost metric into your largest line item. Avoid unbounded IDs such as user_id and request_id on request counters, because every distinct value mints a new billable timeseries. An r/devops thread on Datadog bills puts it plainly: "People often get huge Datadog bills because they added an id or some unbounded tag which resulted in high custom metrics"; one commenter in the same thread reported cutting their bill almost 40%, at least $120K less monthly, after fixing it.
Practitioner accounts show how large a single cardinality mistake can get. An SRE at Indeed found their most expensive metrics carried cardinalities upwards of 200,000 and trimmed roughly $100K in annual metric costs by cleaning them up. Sysdig published a modeled scenario, rather than a customer invoice, in which adding a single product_id label to a transactions metric produced 20 million custom metrics and a modeled $997,500 per month.
Cardinality in Kubernetes and containers
Kubernetes multiplies cardinality by design, because pods are ephemeral and their identifiers are unique. Every rollout, job run, and container restart creates new tag values, which means new timeseries. Two collectors dominate:
- cAdvisor (kubelet container metrics): cAdvisor emits per-container series, and Datadog classifies
container_idanddisplay_container_nameas high-cardinality tags because each container restart generates a new timeseries. - kube-state-metrics: A single pod generates around 40 metrics from Kubernetes State Metrics, each labeled with unique values like
pod,uid, andcontainer_id. Multiply by pod churn from Deployments, Jobs, and CronJobs and the series count compounds on every rollout.
Datadog's Agent defends against this with three tag cardinality levels: low for cluster-level tags like kube_namespace, orchestrator for pod-level tags like pod_name, and high for container-level tags like container_id. Both controlling environment variables, DD_CHECKS_TAG_CARDINALITY and DD_DOGSTATSD_TAG_CARDINALITY, default to low. The common failure mode is raising them to high for a debugging session and forgetting to revert.
Metric types and when to use each
Datadog supports six submission types, and the type you choose changes how many timeseries you pay for per tag combination:
The count vs. gauge distinction trips people up. A count answers "how many times did this happen since the last flush," and Datadog stores it as a RATE. A gauge answers "what is the value right now," and only the last value per flush interval survives. Instrument request totals as counts and queue depth as gauges; reversing them produces meaningless graphs. Reach for DISTRIBUTION only when you need percentiles computed globally across hosts, and remember that enabling percentile aggregations doubles the timeseries count: 4 tag combinations becomes 40 custom metrics.
Ways to submit custom metrics
You choose the submission path based on where the metric originates.
DogStatsD is the default for application code. Your app fires UDP datagrams at the Agent on port 8125, and the Agent aggregates and flushes every 10 seconds. The Python client looks like this:
from datadog import initialize, statsdinitialize(statsd_host="localhost", statsd_port=8125)statsd.increment("checkout.completed", tags=["env:prod", "service:payments"])Every tag in that list participates in the cardinality multiplication described above, so treat the tags argument as a billing decision.
The HTTP API fits serverless functions, batch jobs, and anything that can't reach an Agent. Datadog does not rate limit metric submission: "Datadog does not rate limit on data point/metric submission... Limits encountered is dependent on the quantity of custom metrics based on your agreement." Payloads to POST /api/v2/series cap at 500 KB compressed and 5 MB decompressed. The absence of a rate limit cuts both ways; nothing at the protocol level stops a runaway loop from submitting millions of new timeseries.
Agent custom checks fit polling scenarios: scraping a third-party endpoint or querying a database or file. You write a Python check the Agent runs on its collection interval.
Naming rules apply across all three paths: names must start with a letter, use only ASCII alphanumerics, underscores, and periods, max 200 characters (under 100 preferred), and are case sensitive. Invalid characters convert to underscores, and metric tags normalize to lowercase.
Sources that generate custom metrics automatically
Metrics you never submit still count toward your custom metrics quota. Datadog's canonical list of custom metric sources includes four generated inside the platform:
- APM span-based metrics: Datadog bills metrics generated from traces as custom metrics, and it creates them "from spans ingested by Datadog APM, regardless of whether a retention filter indexes those spans." They inherit whatever grouping cardinality you configure; Datadog's own docs warn against grouping by "unbounded or extremely high cardinality attributes like timestamps, user IDs, request IDs, or session IDs." These bill under the custom metrics allotment, not the span allowance.
- Log-based metrics: Datadog bills "metrics created from ingested logs" as custom metrics, and percentile metrics generated from them are billed as custom metrics too.
- RUM event-based metrics: Datadog computes these from 100% of ingested RUM traffic, not only the data retained in the RUM Explorer. Sampling what you retain does not sample what you're billed for.
- Live process-based metrics: Datadog bills process-based metrics as custom metrics, and they always carry the
proc.prefix.
A team that carefully governs DogStatsD instrumentation can still blow the quota through a single log-to-metric rule grouped on a request ID.
How to monitor and audit custom metric usage
Datadog splits usage investigation across Metrics Summary, Metrics Volume Management, and Usage Details, so auditing them should be routine, not a post-invoice panic.
The Metrics Summary page lists metrics reported over the past hour, day, or week. Its per-metric side panel shows ingested custom metrics, indexed custom metrics, reporting hosts, and the count of unique tag values, with a tags table showing which tags are queryable. A cardinality estimator previews the billing effect of a proposed tag configuration before you save it (the metric must be older than 48 hours).
The Metrics Volume Management page surfaces:
- The top 500 metrics by ingested and indexed volume
- The top 500 spiking cardinality metric names
- The top 500 metrics by estimated real-time cardinality
- The top 500 metrics by change in volume
- A Custom Metrics Tags Cardinality Explorer that helps "pinpoint the tag keys driving the spike"
For attribution against your bill, the Usage Details page shows the top 5,000 custom metrics with average per-hour counts and each metric's contribution percentage to overall usage, exportable as CSV up to 300,000 metrics.
Strategies to control custom metric costs
The only timeseries that cannot become billable is the one that never leaves the node, so the controls are ordered from source to backend:
- Keep Agent tag cardinality at
low: TheDD_CHECKS_TAG_CARDINALITYandDD_DOGSTATSD_TAG_CARDINALITYdefaults already protect you; audit any override toorchestratororhighand revert debugging changes. - Drop high-cardinality tags before ingestion: Container exclusion variables (
DD_CONTAINER_EXCLUDE_METRICS,DD_CONTAINER_INCLUDE_METRICS) and integration-levelmetric_patternsfilter at the Agent. Datadog's Agent-side metric filtering, currently in Preview, starts at Agent v7.67.0, with later versions recommended or required depending on whether you filter DogStatsD or Agent integration metrics. It drops up to 10,000 metric names before they leave the node. An OpenTelemetry Collector in front of Datadog can also delete high-cardinality attributes with its processors; leboncoin reduced its Datadog custom metrics bill 30% by identifying and excluding high-cardinality tags this way. - Configure Metrics without Limits™ tag allowlists: This feature decouples custom metric ingestion and indexing: you select an allowlist of tags to remain queryable and drop the rest from the billable index, in-app, with no Agent changes. Note the two-track billing: configured metrics incur both an ingested charge and an indexed charge, while unconfigured metrics bill on indexed volume alone. Datadog claims configuring unqueried metrics can cut average custom metrics usage by up to 70%. Since it's a backend control, it reduces the indexed charge but never stops data from being sent, and the Metric Name Pricing transition means you should confirm which model your account is on before relying on it.
- Manage metric configurations as code: At hundreds of services, tag allowlists and pipeline rules maintained by hand drift. Defining them in Terraform alongside the rest of your infrastructure keeps cardinality decisions reviewable in pull requests instead of buried in UI state.
Wolt's platform team cut indexed custom metric volume from 3.99M to 2.47M timeseries after finding the Datadog AWS integration was auto-appending unused AWS metadata tags that accounted for roughly 40% of total custom metric volume. In its modeled list-price comparison, the broader optimization path reduced monthly cost from about $457,500 to $123,500.
How Datadog custom metrics pricing compares
Everything above is management of a billing model in which instrumentation decisions and price are the same decision. Every tag an engineer adds is a purchase order, which is why Datadog custom metrics governance becomes an ongoing engineering function rather than a one-time setup. Other models decouple the two.
Prometheus
Prometheus turns cardinality into a resource-capacity problem. Licensing has no per-timeseries fee; high cardinality costs RAM, CPU, disk, and query latency instead, and the failure mode is operational rather than financial. You control cardinality with relabel_configs, metric_relabel_configs, sample_limit, label_limit, and recording rules, and you pay in engineering time.
OpenTelemetry
OpenTelemetry decouples instrumentation from the vendor. Because the Collector sits between your services and any backend, its filter, transform, and attributes processors can drop metrics or high-cardinality attributes before any vendor sees them. The OTel SDK enforces a default cardinality limit of 2,000 unique attribute combinations per metric, overflowing into an otel.metric.overflow=truedatapoint rather than an invoice line.
groundcover
groundcover removes metric count and cardinality from the license calculation. Pricing is flat per node: the actively monitored nodesaveraged over the month, $30/host/month on Pro, with no per-metric, per-GB, or per-seat charges.
groundcover's BYOC (Bring Your Own Cloud) architecture runs the data plane, telemetry processing and storage, inside your VPC. Metrics use a VictoriaMetrics metrics backend, fully PromQL-compatible, so existing Grafana dashboards and PromQL queries carry over.
High cardinality still consumes storage in your VPC, and your cloud provider bill for running the backend does scale with volume. The license stays tied to node count, so tagging decisions go back to being engineering decisions. To validate the architecture on real workloads, use the free tier on one Kubernetes cluster and send high-cardinality metrics through it. The license fee does not change; your BYOC hosting footprint is the variable to monitor.







