Observability cost  / field guide
Practitioner field guide · 2026-09-23

The meter runs on cardinality

How production systems keep the cost of watching themselves from outgrowing the systems being watched. Reconstructed from the incident record at GitLab and Datadog, the pricing sheets of three clouds, the source and rejected pull requests of Prometheus and OpenTelemetry, and first-person accounts from Zendesk, eBay, Netflix, Zerodha, Wix and Roblox. A reader leaves able to name their telemetry billing atom, choose between the two containment philosophies on purpose, and price the funnel before the finance team does.

35 primary sources 12 production systems 9 incidents Evidence through September 2026 Read: 22 min
01

The territory

A system's description of itself grows faster than the system, and the mature response, everywhere the record is public, is industrial-scale deletion.

99–100%
What Zendesk's most common log exclusion filter throws away, across 1,435 filters
1/1024
Google's production trace sampling rate in Dapper; full tracing cost 16.3% latency
5B
Active time series Roblox reports in its self-hosted metrics store
$5
Datadog list price per 100 indexed custom metrics per month; a metric is one name-and-tag combination

Strip the product names away and the problem is this: every request through a modern system emits a description of itself, that description is multiplied by the number of services it touches and the number of dimensions each one records, and the multiplication compounds faster than traffic. Datadog's own storage team measured its data volumes growing 30x between 2017 and 2022. Netflix hit the wall as early as May 2011, when, at roughly two million distinct time series, "the monitoring system was regularly failing to keep up with the volume of data". The organisations that survived this did not buy their way out with bigger storage. They built funnels.

The surprise in this record, and the reason to read on, is how much gets thrown away by the people who take observability most seriously. Google's Dapper kept one trace in 1,024 at generation and then sampled again at the collection tier, "often as low as 0.01% for high-traffic services", and still wrote more than a terabyte of sampled trace data per day in 2010. Zendesk, in a guest post published by its own vendor, reports 1,435 log exclusion filters in steady state, the most common of which drops 99 to 100% of what it matches, and an ingestion-to-indexing ratio of 10:1. Deletion is not a failure of observability discipline. Deletion, done at named stages with named keep-rates, is what observability discipline looks like at scale.

The second thing the record teaches is what the meter actually runs on. For metrics, every pricing sheet and every out-of-memory incident points at the same unit: the series, one unique combination of a metric name and its tag values, alive in RAM somewhere. Datadog bills it by name, AWS prices the metric-month, and GitLab's ingesters OOMed on "high numbers of in-memory series". Volume, gigabytes and datapoints per second, is what logs and traces are priced in; cardinality is what metrics are priced in, on both the invoice and the heap.

Scope: this guide covers cost and scale containment for metrics, logs and traces in production, the mechanisms, the prices and the incidents. It deliberately does not cover alert and dashboard design, compliance-driven retention for security logs, continuous profiling, or feature comparisons between vendors.

Evidence limits of this build

This guide was assembled inside a build environment whose network policy allowlists a small set of hosts. Well-known accounts from Uber, Slack, Cloudflare, Pinterest, Shopify, Grafana Labs and Honeycomb's blog could not be fetched, so they are not cited; several papers are cited from byte-identical mirrors with the canonical venue named. The widely reported "$65M per year" Datadog customer from the May 2023 earnings call is deliberately absent for the same reason: none of its primary sources could be verified here, and this guide does not cite what it could not fetch.

Figure 1 · The funnel every mature pipeline converges on

SDK caps (OTel overflow series)

scrape limits, per-tenant 429s

sampling and exclusion (Dapper 1/1024; Zendesk filters at 99-100%)

rollups at 4d and 16d (Netflix)

Emitted by code · 100%

Leaves the process

Accepted at ingest

Kept queryable (hot tier)

Archive: object storage

SDK caps (OTel overflow series)

scrape limits, per-tenant 429s

sampling and exclusion (Dapper 1/1024; Zendesk filters at 99-100%)

rollups at 4d and 16d (Netflix)

Emitted by code · 100%

Leaves the process

Accepted at ingest

Kept queryable (hot tier)

Archive: object storage

Each stage has a published keep-rate somewhere in the record; end to end the keep-rate spans three to four orders of magnitude. Sources: Dapper, 2010, Zendesk, 2025, Netflix Atlas docs.
Diagram source
02

How it is actually built

Six layers recur across every published system; what varies is where each organisation puts the deletion decision, and who is allowed to make it.

Figure 2 · Reference architecture for telemetry cost containment

Two-tier storage

The decision layer

Platform team: the edge

Service teams own this

unindexed, cheap

age out, roll up

rehydrate on demand

Instrumented code
SDK cardinality caps

Node or cluster agent
(topology is a cost lever)

Distributor / gateway
per-tenant limits, 429s

Samplers, filters,
aggregation and rollup rules

Hot tier: in-memory series
(RAM = cardinality = money)

Cheap tier: object storage,
columnar files

Query path
per-query cost ceilings

Two-tier storage

The decision layer

Platform team: the edge

Service teams own this

unindexed, cheap

age out, roll up

rehydrate on demand

Instrumented code
SDK cardinality caps

Node or cluster agent
(topology is a cost lever)

Distributor / gateway
per-tenant limits, 429s

Samplers, filters,
aggregation and rollup rules

Hot tier: in-memory series
(RAM = cardinality = money)

Cheap tier: object storage,
columnar files

Query path
per-query cost ceilings

Reconstructed across Datadog's Husky, GitLab's Mimir deployment, Netflix Atlas, Facebook's Canopy and Loki's limit taxonomy. The decision layer is the box that varies most; the hot tier is where cardinality becomes money.
Diagram source

Start at the bottom of the money, not the top of the data flow. The hot tier is a RAM budget, and everything upstream exists to protect it. Facebook's Gorilla stated the constraint plainly in 2015: two billion series at 16 bytes per point would need 16 TB of RAM, so the team compressed points to an average of 1.37 bytes and bounded the window to 26 hours. Google's Monarch is the same shape a generation later, "close to a petabyte of compressed time series data in memory". Grafana's Loki documentation writes the rationale into its per-tenant stream cap: "Active streams are held in memory buffers in the ingesters, and if this value becomes sufficiently large then it will cause the ingesters to run out of memory". When you see a limit knob in any of these systems, read it as a RAM fence with a price tag.

The layer above the store is the edge, and its defining property is that it refuses. Loki's distributors answer over-limit tenants with named 429s. Prometheus's scrape limits, sample_limit, label_limit and friends, go further: when one trips, "the entire scrape will be treated as failed", nothing partial, nothing silently dropped. Canopy, Facebook's tracing system, rate-limits with a token bucket "both globally and per-tenant". Three independent systems, one design conviction: at the edge, the writer is untrusted, and refusal is the only response that keeps the blast radius on the writer's side of the line.

The decision layer between edge and store is where organisations diverge, because it is where judgement lives. Dapper put a uniform coin-flip in the SDK and a second, more aggressive sampler at collection. Canopy replaced the coin-flip with named sampling policies, each carrying an owner, a strategy, restraints and a lifetime; policy, not physics. Zendesk's version is 1,435 exclusion filters maintained by hand against a two-price contract. Netflix's version is age-based: hold everything briefly, then "rollup by dropping the node dimension" at four days and again at sixteen. These are four different answers to one question: who signs off on what gets forgotten, and when.

Two boxes in figure 2 are easy to miss and both are documented cost levers. Agent topology: eBay measured a per-node DaemonSet costing roughly 200 MB and 0.6 cores per instance of pure overhead, and moving to cluster-local scraping agents saved "roughly 90%" of that resource bill at a fleet of 1.5 million endpoints. And the query path: GitLab's readiness review for Mimir names the "poison query" as a risk that survived its whole platform migration, and Prometheus now has a design proposal for pre-execution query cost estimates on the grounds that "a single expensive query can hurt a whole Prometheus". Containment that only guards the write path is half a containment.

The decision layer

Samplers, exclusion filters, aggregation and rollup rules. The one layer where every organisation's answer differs, because it encodes who may decide what is forgettable. Canopy gives each policy an owner and a lifetime; Zendesk curates filters by hand; Netflix keys the decision to age.

Runs this way at: Facebook, Zendesk, Netflix

The hot tier

In-memory series storage with a deliberately bounded window. Gorilla held 26 hours; Atlas holds recent data in memory because query latency demands it; Mimir ingesters hold active series and OOM when churn spikes. RAM here is the physical form of the cardinality bill.

Runs this way at: Facebook, GitLab, Google

The cheap tier

Object storage or columnar files holding what the hot tier aged out, queryable slowly or after rehydration. Datadog built Husky to burst readers over it on demand; Zerodha holds 30 billion log lines in 2.5 TB of ClickHouse; Nexthink archives to S3 without indexing at all.

Runs this way at: Datadog, Zerodha, Nexthink

03

The decisions that matter

Three forks carry most of the consequences, and the record contains a genuine argument about each one.

The sharpest recorded argument is about what a limit should do when it trips. In April 2026 a contributor opened a pull request adding a hard cardinality_limit to the OpenTelemetry Collector's batching layer. Five reviewers approved it. It died anyway, closed unmerged in September 2026, on one maintainer's objection:

"I'm not sure I understand the purpose of adding this failure point... memory is bounded without rejecting anything. If we want to add this hard cap for some reason, we should remove LRU." dmitryax, OpenTelemetry Collector pull request 15225, September 2026

That sentence names the two containment philosophies cleanly. Rejection fails loudly at the boundary: Prometheus fails the whole scrape, Loki returns a 429 with a named reason, and the operator finds out immediately. Eviction degrades quietly inside: the OTel SDK spec caps cardinality by folding excess series into a single otel.metric.overflow series, an LRU keeps memory bounded, and nothing pages. The collector maintainers judged that stacking a rejection knob on top of an eviction design adds a failure point without adding safety. Prometheus, from the opposite pole, has kept a maintainer's own proposal for scrape-time cardinality capping open and unresolved since 2022, partly because a partial drop would blur exactly the loud-failure semantics it relies on.

When the limit trips, does the system reject or evict?

Chosen
Rejected (by those systems)
  • Silent partial drops at the edge, argued down because an unnoticed gap is worse than a visible refusal
  • In the OTel Collector the inverse held: a hard cap was rejected because LRU eviction already bounds memory
Flips when
  • The writer is untrusted or multi-tenant: reject at the edge, blast radius stays with the writer
  • The pipeline is trusted and continuity beats completeness: evict, and alert on the overflow series instead

The second fork is where the trace keep-decision runs. Head sampling decides at the root span, cheaply: Dapper's uniform 1/1024, refined by adaptive sampling parameterised by desired traces per unit time. Tail sampling holds every span of a trace in memory until it can judge the whole thing, which is how you keep every error and every slow outlier: Honeycomb's Refinery keeps "one out of every 1,000 traces for requests that return 2xx" while keeping every 5xx. The price is written in the OTel tail sampler's own README: the buffer is a circular one, and "this can cause a trace to be dropped before it's sampled", while every knob that reduces that risk increases memory. A 2025 issue names the consequence for the bill: "memory usage scaling linearly to throughput. Higher memory requirements translates to higher hardware cost." OTEP 235 exists precisely because real systems end up doing both, and two samplers that decide inconsistently destroy the statistics; its threshold mechanism makes head and tail stages compose.

Do traces get sampled at the head or at the tail?

Chosen
  • Google (Dapper): head, 1/1024, because at that rate overhead became unmeasurable
  • Honeycomb (Refinery), Facebook (Canopy edge policies): tail or policy-based, to keep 100% of errors
Rejected
  • Full tracing: Dapper measured it at 16.3% latency overhead
  • Tail-everything at high throughput: buffer RAM grows linearly with traffic, and the circular buffer starts dropping undecided traces
Flips when
  • Error and latency outliers are the point of tracing: tail wins while collector RAM is affordable
  • Throughput grows past what the decision buffer can hold: move the bias to the head, carry the threshold in TraceState (OTEP 235) so stages compose

The third fork is commercial: drop before ingest, or ingest everything and index a fraction. The vendors have built a two-price split for the second option, and the practitioner accounts show both being worked hard. Zendesk ingests ten times what it indexes and holds the line with exclusion filters. Nexthink goes further on the cheap side, archiving logs directly to S3 "without ingesting or indexing them". Zerodha opted out of the split entirely, moving logs from ELK to self-hosted ClickHouse: 30 billion log lines in 2.5 TB where the old stack needed 13 TB for the same order of volume, at less than half the hourly infrastructure cost. The flip condition is not subtle: the two-price split is worth paying for when someone else runs the platform and your query patterns are unpredictable; it stops being worth paying for when your ingest is dominated by data nobody has ever queried, which is exactly what Zendesk's 99-to-100% filters say out loud.

Figure 3 · Decision tree: where should this telemetry be cut?

no

yes

cardinality

volume

yes

no, statistics suffice

volume, and it is logs

rarely

only recent data

Is the writer
trusted?

Is the signal's cost driven
by cardinality or volume?

Are errors and outliers
the point of keeping it?

Queried since
it was ingested?

Reject at the edge:
per-tenant limits, failed scrapes
(Prometheus, Loki)

Cap in the SDK, evict to an
overflow series, alert on it
(OTel spec)

Tail-sample with error bias
(Refinery), budget buffer RAM

Head-sample uniformly,
compose via OTEP 235 thresholds
(Dapper)

Index a fraction, archive the rest
unindexed (Zendesk 10:1, Nexthink)

Roll up by age, drop the
node dimension (Netflix)

no

yes

cardinality

volume

yes

no, statistics suffice

volume, and it is logs

rarely

only recent data

Is the writer
trusted?

Is the signal's cost driven
by cardinality or volume?

Are errors and outliers
the point of keeping it?

Queried since
it was ingested?

Reject at the edge:
per-tenant limits, failed scrapes
(Prometheus, Loki)

Cap in the SDK, evict to an
overflow series, alert on it
(OTel spec)

Tail-sample with error bias
(Refinery), budget buffer RAM

Head-sample uniformly,
compose via OTEP 235 thresholds
(Dapper)

Index a fraction, archive the rest
unindexed (Zendesk 10:1, Nexthink)

Roll up by age, drop the
node dimension (Netflix)

Terminal nodes are actions from the record, each practised by a named organisation in the evidence wall. The tree assumes the billing atom is known; if it is not, start at rung 1 of the ladder instead.
Diagram source
DecisionChosenRejectedBecauseFlips whenEvidence
Limit semanticsFail the whole scrape (Prometheus)Partial silent dropA visible refusal beats an unnoticed gapTrusted single-team pipeline: evict to overflow and alertPrometheus docs
Cap in collector batchingLRU eviction onlyHard cardinality cap (5 approvals)"Memory is bounded without rejecting anything"The cap is the product being sold, per-tenant, at a platform edgePR 15225
Trace keep-decisionHead at 1/1024 (Google)Full tracing16.3% measured latency at 1/1Errors are the point and RAM is affordable: go tailDapper
Log economicsIngest 10x, index 1x (Zendesk)Index everythingMost matched volume is never queriedIngest itself dominates: drop at source or self-host columnarZendesk, Zerodha
Metrics retentionAge-tiered rollups (Netflix)Uniform retentionOld data is queried at coarser grainRegulated workloads that must replay raw historyAtlas docs
Buy or self-host metricsSelf-host (Zerodha, Wix, Grammarly)SaaS per-series pricingReported savings up to 10x at high churnNo team to own a new incident class; GitLab's inter-AZ network bill shows self-hosting has its own meterCase studies, GitLab
Agent topologyCluster-local scraping (eBay)Per-node DaemonSetRoughly 90% resource savings at 1.5M endpointsNode-level signals (kernel, disk) that only a node agent can seeeBay
04

What broke in production

The incidents cluster into three classes: the watcher eats itself, the watcher fails closed, and the containment machinery degrades the watching silently.

Class one is self-inflicted cardinality, and it is the best documented because GitLab publishes its incident reviews in a public tracker. The pattern is always the same mechanism at different magnitudes: something multiplies label values, the in-memory series count climbs, and the process that holds them dies. At GitLab in October 2025 the multiplier was routine pod churn from frequent deployments; 18 of 210 Mimir ingesters OOMed, quorum broke, and metrics writes failed platform-wide for 25 minutes. At token.place in September 2026 the multiplier was default Flask instrumentation keeping request-controlled URL paths as label values; the series count went from 28,964 to 71,056 in eighteen minutes and the scrape payload alone reached 7.79 MB every 30 seconds. Same curve, five orders of magnitude apart in fleet size. The transferable rule: any label whose values are chosen by traffic rather than by an engineer is an unbounded meter, and the meter runs whether or not anyone is watching it.

Figure 4 · Failure path of a cardinality burst, GitLab's Mimir outage

On-callMimir ingesters, 210Scrape agentsDeploys, pod churnOn-callMimir ingesters, 210Scrape agentsDeploys, pod churnreplication quorumlostnew pods, fresh label valuesremote-write, in-memory seriesclimbOOM kill on 18ingesterswrites fail platform-wide (25 min)dashboards missing the verymetrics neededrestart, then migrate toKafka-based ingest path
On-callMimir ingesters, 210Scrape agentsDeploys, pod churnOn-callMimir ingesters, 210Scrape agentsDeploys, pod churnreplication quorumlostnew pods, fresh label valuesremote-write, in-memory seriesclimbOOM kill on 18ingesterswrites fail platform-wide (25 min)dashboards missing the verymetrics neededrestart, then migrate toKafka-based ingest path
Ordinary deployment activity manufactured the series burst; the platform's own redundancy arithmetic (quorum) converted 8.5% of ingesters failing into a 100% write outage. From GitLab incident review 20782, October 2025.
Diagram source
Postmortem

Pod churn OOMs the metrics store

AssumptionIngesters sized for steady-state series counts would absorb deployment-driven churn.
What happened"OOM kill on multiple ingesters due to high numbers of in-memory series"; 18 of 210 ingesters down broke replication quorum.
Blast radiusFull metrics write outage, 25 minutes, severity 2; dashboards degraded during their own incident.
FixMigration to the Kafka-based Mimir ingest-storage architecture, chosen explicitly for "cardinality explosions".
Design ruleSize the hot tier for churn, not for steady state; deployment frequency is a cardinality input.
Postmortem

Traffic-controlled labels as a self-DoS

AssumptionDefault framework instrumentation is safe to expose to the internet.
What happenedFlask instrumentation kept raw request paths as label values; series grew 28,964 to 71,056 in 18 minutes; the exposition payload hit 7.79 MB per 30-second scrape and the container hit 92.4% of its 256 MiB limit.
Blast radiusRoughly 87 minutes of production relay outage.
FixRe-enable gated on proving "unmatched paths map to a bounded label set".
Design ruleEvery label set needs an upper bound an engineer chose; recovery is not done until the bound is proven, not just observed.
Postmortem

Meta-monitoring saturates its own platform

AssumptionRecording rules that watch the metrics platform are cheap relative to what they protect.
What happened"Overly expensive meta-monitoring recording rules that created high-cardinality queries, saturating the system and resulting in backlogs and instability."
Blast radiusMimir read-path instability and dashboard degradation until per-tenant query concurrency was raised.
Fixmax_queriers_per_tenant raised from 10 to 20 for the meta-monitoring tenant.
Design ruleMeta-monitoring is a tenant like any other; give it a budget and a quota rather than assuming it is small.
Postmortem

The telemetry platform fails closed

AssumptionFavouring data correctness over availability is the safe default for a monitoring product.
What happenedA systemd security auto-update deleted container network routes across tens of thousands of nodes; AWS auto-remediation then replaced about 60% of instances, destroying local state. Systems biased to "full stop over showing almost correct data" went down in a "square-wave failure pattern".
Blast radiusAll products across five regions from 06:03 UTC 2023-03-08; services declared operational 2023-03-09 08:58 UTC; customers' "monitors were unavailable and not alerting"; 500 to 750 engineers responding in shifts.
FixPersist intake earlier, serve live data before backfill, stronger retry backoff, earlier dead-letter queues; Datadog reports a 30% decline in significant monitor-affecting incidents since.
Design ruleA telemetry platform is a dependency of every other incident response; its correct failure mode is degraded-but-current, never correct-but-absent.
Postmortem

The read path dies while collection survives

AssumptionIf Prometheus is up, we can see.
What happened"Prometheus and alertmanager were still operational, Thanos was completely unavailable"; dashboards timed out because the query layer, not collection, had failed.
Blast radiusRoughly 600 minutes of degraded observability at GitLab; detected via humans noticing Grafana timeouts.
FixQuery-path capacity and, eventually, the platform migration recorded in the Mimir readiness review after "increasingly large numbers of incidents related to Thanos and Prometheus issues".
Design ruleCollection and query are separate failure domains; alert on the read path directly, because the write path's health says nothing about it.
Postmortem

Derived metrics vanish, raw metrics survive

AssumptionIf ingestion is healthy, the metrics people actually look at are healthy.
What happened"Our thanos rule processes abruptly increased their memory demand and saturated their available memory capacity"; recording-rule outputs, including apdex, went missing while raw series kept flowing.
Blast radiusOne hour fifty minutes without derived metrics, rated severity HIGH with no customer impact; troubleshooting capability was the casualty.
FixMore memory for the rule evaluators and reverting a recently added rule set.
Design ruleRule evaluation is a workload with its own capacity plan; every added recording rule is load you provisioned for the worst day, not the average one.

One class is conspicuously missing from the public record: the bill as the incident. Practitioner postmortems for observability cost overruns, written by the team that paid, are rare to the point of absence; the genre is dominated by competing vendors' marketing. GitLab's cost tracker is the nearest thing, and its finding is instructive: the surprise line item in self-hosted metrics was "much higher than expected inter-zone AZ traffic costs" from replication, not storage or compute, and the levers it considered, single-AZ operation and spot instances, trade away exactly the redundancy the platform exists to provide. Treat this gap as information: if you want to know what a cost blow-up looks like before the invoice, nobody has published the timeline, so instrument your own meter (rung 1 of the ladder) rather than waiting to read about someone else's.

05

Numbers you can plan against

Scale points from the systems that published them, and list prices from the three meters an architect is most likely to face.

MetricValueAtContextAs ofSource
Active series3 billioneBaySherlock.io, 1.5M scraped endpoints, 40M samples/s2022eBay on OTel blog
Active series5 billionRobloxSelf-reported, 120M datapoints/s ingest2023, checked 2026VM case studies
Series churn150M new/dayWixAgainst 50M active per instance; churn, not active count, drives index growthchecked 2026VM case studies
Hot-tier compression1.37 bytes/pointFacebookDown from 16; made 26h in RAM affordable at 12M points/s2015Gorilla, VLDB
In-memory store~1 PBGoogleMonarch, compressed, terabytes/s ingest, 38 zones2020Monarch, VLDB
Trace sampling1/1024 head, to 0.01% at collectionGoogleFull tracing measured at 16.3% latency overhead; sampled residue still >1 TB/day2010Dapper
Traces recorded1.3 billion/dayFacebookCanopy, per-tenant token buckets at the edge2017Canopy, SOSP
Single-server boundtens of millions of seriesDigitalOcean192 Prometheus servers, 200M+ series, 2M+ samples/s fleet-wide2018KubeCon slides
Log storage ratio2.5 TB vs 13 TBZerodha30B lines in ClickHouse vs 28B in ELK; node cost $1.14/h vs $2.67/h2023Zerodha
Ingest-to-index ratio10:1Zendesk1,435 exclusion filters; 4x volume cut on the hottest service2025Zendesk
Custom metrics price$5 / 100 / month indexed; $0.10 / 100 ingestedDatadogA metric is one name-and-tag-value combination; histograms multiply it2026 listPricing list
Metric-month price$0.30 tiering to $0.02AWS CloudWatchFirst 10k at $0.30, past 1M at $0.02; logs $0.50/GB ingest, $0.03/GB-mo storage2026-09-22Price List API
Log ingest price$0.50/GiB incl. 30dGoogle CloudThen $0.01/GiB-mo; monitoring $0.2580/MiB tiering down; managed Prometheus $0.06/M samples2026, logging price effective 2024-10GCP pricing
Indexed log events$1.70/million (15-day)DatadogVersus $0.05/million in Flex storage: a 34x spread inside one product2026 listPricing list
Worked mid-market bill~$18,400/monthOneUptime scenarioCompetitor's list-price model for a 50-person team; a claim, not a measurement2026-03OneUptime

A workable cost model needs only three variables, one per signal. Metrics: active series times price per series-month, where the series count is driven by churn (Wix's 150 million new series a day against 50 million active is the cleanest published illustration that churn dominates). At Datadog's list price of $5 per 100 per month, an application emitting 10,000 custom series costs $500 a month before a single log line; the same 10,000 on CloudWatch's first tier is $3,000, falling steeply with volume discounts. Logs: gigabytes ingested times the ingest price, plus events indexed times the index price; Datadog's own sheet spreads 34x between an indexed event and a Flex-stored one, which is the entire economic argument for the Zendesk pattern. Traces: spans kept per second times retention, where the keep-rate is your sampling policy; Dapper's numbers say the runtime overhead argument ends at roughly 1/16 and everything below that is storage economics. These are derived illustrations from the linked list prices, not quotes; negotiated contracts sit below list, sometimes far below.

Figure 5 · The two-price split: deletion decided after ingestion

ingest
$0.10/GB

~1 in 10
$1.70/M events

bulk
$0.05/M events

Log stream

Pipeline:
exclusion filters
(Zendesk: 1,435)

Indexed
searchable 15d

Flex / archive
(Nexthink: straight
to S3)

ingest
$0.10/GB

~1 in 10
$1.70/M events

bulk
$0.05/M events

Log stream

Pipeline:
exclusion filters
(Zendesk: 1,435)

Indexed
searchable 15d

Flex / archive
(Nexthink: straight
to S3)

Vendors now price acceptance and queryability separately, so the keep-decision moves inside the pipeline; the spread between the two prices inside one product is 34x for log events. Prices from Datadog's 2026 list; the operating pattern from Zendesk and Nexthink.
Diagram source
Read these carefully

Scale figures from eBay, Roblox, Wix, Zerodha and Zendesk are self-reported and unaudited; the Roblox and Wix rows live in a vendor-curated document. Grafana's "1 billion active series" for Mimir is the vendor's own internal test, labelled as such. All prices are 2026 list prices for US regions and go stale silently; the CloudWatch row carries its exact publication date because the Price List API stamps one. No independent measurement exists for any SaaS-versus-self-host comparison in this corpus; every migration figure comes from the team that chose to migrate.

06

The evidence wall

Every source behind this page, graded. The postmortems and the rejected pull request are the load-bearing items; read those two tiers first.

Postmortem GitLab2025-10

Incident review: Mimir unavailable

Pod churn drove in-memory series high enough to OOM 18 of 210 ingesters; quorum loss turned 8.5% component failure into a 100% write outage for 25 minutes.

Carry forwardDeployment frequency is a cardinality input; size the hot tier for churn.
gitlab.com/gitlab-com/gl-infra/production/-/issues/20782
Postmortem Datadog2023-05

2023-03-08 multi-region outage, with two engineering deep dives

A systemd auto-update deleted CNI routes fleet-wide; five regions, all products, customers' monitors "unavailable and not alerting"; 500 to 750 engineers in shifts.

Carry forwardYour incident response depends on someone else's telemetry platform staying up; have an out-of-band path for the alerts that matter most.
datadoghq.com/blog/2023-03-08-multiregion-infrastructure-connectivity-issue
Postmortem Datadog2025-10

Failure is inevitable: learning from a large outage

Names the false assumption behind the 2023 outage in one phrase: a bias toward "full stop over showing almost correct data", producing a "square-wave failure pattern".

Carry forwardFor telemetry, degraded-but-current beats correct-but-absent; design the platform to fail open.
datadoghq.com/blog/engineering/rethinking-reliability
Postmortem GitLab2026-05

Meta-monitoring saturates Mimir

The recording rules that watch the metrics platform generated the high-cardinality query load that destabilised it; fixed by raising the meta-tenant's querier quota.

Carry forwardMeta-monitoring is a tenant; give it a quota and a cost budget like any other.
gitlab.com/gitlab-com/gl-infra/production/-/issues/22205
Postmortem token.place2026-09

Production relay metrics-cardinality OOM

Default Flask instrumentation kept request-controlled paths as labels: 28,964 series to 71,056 in eighteen minutes, 7.79 MB scrape payloads, 87 minutes of outage. A small system, which is why the whole mechanism is visible end to end.

Carry forwardAudit default instrumentation for traffic-controlled label values before exposing anything to the internet.
token.place outage report, GitHub
Postmortem GitLab2020-04

Lack of observability: Thanos down, Prometheus fine

Ten hours of degraded visibility in which collection was healthy and the query layer was not; detection was a human noticing Grafana timeouts.

Carry forwardAlert on the read path directly; write-path health tells you nothing about it.
gitlab.com/gitlab-com/gl-infra/production-engineering/-/issues/9877
Postmortem GitLab2023-02

Recording-rule outputs go missing

Thanos rule evaluators OOMed; apdex and other derived metrics vanished for nearly two hours while raw ingestion stayed healthy. Rated HIGH with zero customer impact.

Carry forwardRule evaluation is a capacity-planned workload; new rules are load, not configuration.
gitlab.com/gitlab-com/gl-infra/production/-/issues/8345
Postmortem GitLab2022-01

Crashlooping Prometheus pod

An OOM crash loop from WAL corruption, worked as a production incident with corrective actions; 45 minutes to mitigate by deleting the corrupt segment.

Carry forwardThe metrics store needs its own runbooks and recovery drills, exactly like a database, because it is one.
gitlab.com/gitlab-com/gl-infra/production/-/issues/6241
Source OpenTelemetry2026-09

PR 15225: cardinality_limit for batch partitions, closed unmerged

A hard cap with five reviewer approvals, rejected on one maintainer's argument that eviction already bounds memory and a rejection knob adds a failure point. The clearest recorded statement of the two containment philosophies.

Carry forwardDecide rejection versus eviction per boundary, on purpose; do not stack both on one component.
github.com/open-telemetry/opentelemetry-collector/pull/15225
Source OpenTelemetry2026

Tail-sampling processor README and its knobs

num_traces (50,000 default), decision_wait (30s default), and a circular buffer whose documented behaviour is that a trace can be dropped before its keep-decision runs.

Carry forwardTail sampling's real price is RAM linear in throughput; treat the buffer as a capacity plan.
tailsamplingprocessor README, GitHub
Source Prometheus2026

Scrape limit semantics in the configuration docs

Every scrape limit defaults to off, and each one that trips fails the entire scrape. The all-or-nothing semantics are a deliberate design position, not an accident.

Carry forwardIf you enable sample_limit, you are choosing visible gaps over silent ones; alert on scrape failure accordingly.
prometheus configuration.md, GitHub
Source Prometheus2022, still open

Issue 11061: cardinality_limit for scrape configs

A maintainer's own proposal to cap unique label values per scrape, open for four years across 15 comments. Upstream has no agreed answer to scrape-time cardinality capping.

Carry forwardDo not wait for the ecosystem to bound your labels; the bound has to live in your instrumentation review.
github.com/prometheus/prometheus/issues/11061
Source VictoriaMetrics2025-07

Issue 9522: the cardinality limiter's own cost

Operators report that hitting the limiter "could lead to full vmstorage degradation since it goes via the slowest path", and that the hourly/daily dual semantics confuse the people who must configure them.

Carry forwardA limiter is a safety valve, not a control plane; if it engages routinely, the fix is upstream.
github.com/VictoriaMetrics/VictoriaMetrics/issues/9522
Source OpenTelemetry2024

The overflow attribute, stabilised

The SDK-level eviction answer: past the cardinality limit, excess series fold into a single otel.metric.overflow series. Stabilised only after Go, C#, Java and Rust had all shipped it.

Carry forwardAlert on the overflow series; it is the one signal that eviction-based containment is active.
opentelemetry-specification issue 3904
ADR OpenTelemetry2023

OTEP 235: sampling threshold propagation

"When sampling is to be performed at multiple points in the process, the only way to reason about it effectively is to make sure that the sampling decisions are consistent." The mechanism: a rejection threshold carried in TraceState, non-decreasing along the path.

Carry forwardIf two stages sample, they must compose; adopt consistent-probability sampling before adding the second stage.
OTEP 235, GitHub
ADR Prometheus2025-2026

Proposal 0089: query cost estimation and limits

Not yet implemented: pre-execution cost estimates and hot-reloadable per-query ceilings, motivated by "a single expensive query can hurt a whole Prometheus" and the fact that today's limits require a restart to change.

Carry forwardRead-path containment lags write-path containment everywhere; budget for poison queries now.
prometheus proposals/0089, GitHub
ADR Grafana2026

Loki's request validation and rate-limit taxonomy

Operational design doc for volume containment as layered per-tenant refusals, with the memory rationale for each limit written next to its default and its recommended ceiling.

Carry forwardPublish the reason next to the limit; an unexplained 429 generates a ticket, an explained one generates a fix.
loki request-validation-rate-limits.md
ADR GitLab2023-11

Mimir production readiness review

The migration record: 18 months of Thanos-related incidents drove the change, the new system ran side by side from November 2023, and the review names the poison-query risk that migration does not remove.

Carry forwardA platform migration resets the incident classes you know; the readiness review is where you write down the ones it keeps.
gitlab.com gl-infra readiness/mimir
Blog Zendesk2025-12

Optimizing Datadog at scale

The steady state of a marquee SaaS observability customer: 1,435 exclusion filters, the most common excluding 99 to 100%, a 10:1 ingest-to-index ratio, and a 4x volume cut on the hottest service.

Carry forwardInside a SaaS contract, the exclusion-filter list is your decision layer; staff and review it like code.
datadoghq.com/blog/zendesk-cost-optimization
Blog eBay2022-12

Why and how eBay pivoted to OpenTelemetry

Sherlock.io at 1.5M scraped endpoints, 40M samples/s, 3B active series; moving from per-node DaemonSets to cluster-local agents saved roughly 90% of the agent resource bill.

Carry forwardAgent topology is a first-class cost decision, separate from what you collect.
eBay on the OTel blog (source markdown)
Blog Netflixliving doc

Atlas overview: the rollup policy

The 2011 drowning at two million series, and the containment that followed: full resolution briefly, node dimension dropped at four days, all metrics rolled up at sixteen, whitelist beyond.

Carry forwardRetention is a function of age and question type, not a single number.
Netflix atlas-docs overview
Blog Zerodha2023-03

Logging at Zerodha

ELK to ClickHouse: 30 billion lines in 2.5 TB against 13 TB before, node cost less than half, retention tiered by log level. A complete self-host counter-example to the two-price split.

Carry forwardColumnar storage changes log economics by roughly an order of magnitude; the trade is owning the platform.
zerodha.tech logging post (source markdown)
Blog Datadog2024-06

Timeseries indexing at scale

30x data growth in five years forced an index rewrite; the rewrite bought 20x higher queryable cardinality on identical hardware and halved the indexing service's cost.

Carry forwardAt the platform layer, cardinality headroom is an engineering artefact, not a fixed law; vendors re-earn their margins this way.
datadoghq.com timeseries-indexing-at-scale
Blog Datadog2022-05

Introducing Husky

The event store behind the two-price split: storage decoupled from compute so a year-deep query can burst readers over cheap storage on demand.

Carry forwardThe cheap tier is only cheap if the read path can burst; check the rehydration story before relying on archives.
datadoghq.com introducing-husky
Case study Wix, Roblox, Grammarly and otherschecked 2026

VictoriaMetrics case studies

First-person scale figures from teams that left Prometheus-family or SaaS stacks: Wix at 50M active series with 150M/day churn, Roblox at 5B active series and 120M datapoints/s, Grammarly reporting 10x cost reduction. Vendor-curated but quoted first-person.

Carry forwardReport churn next to active series; the pair, not either number, sizes the index.
VictoriaMetrics CaseStudies.md
Case study Nexthinkchecked 2026

Containment inside a SaaS contract

Archive to S3 without ingesting or indexing, keep custom metrics at 9.9k against 141 integrations' worth of included metrics, "for a similar budget, we are now processing significantly more data".

Carry forwardThe included-metrics allotment is real money; count it before adding custom series.
datadoghq.com/case-studies/nexthink
Paper Google2010-04

Dapper (tech report)

1/1024 head sampling, a second collection-tier sampler down to 0.01%, full tracing measured at 16.3% latency overhead, and still more than a terabyte of sampled traces a day. Fetched from Google's own publication bucket.

Carry forwardBelow roughly 1/16, sampling stops being a performance argument and becomes a storage-economics one.
Dapper PDF, storage.googleapis.com
Paper Facebook2015-08

Gorilla (VLDB 2015, cited from a mirror)

16 bytes per point to 1.37 via XOR compression, a 26-hour in-memory window as an explicit requirement, and clusters that doubled twice under growth anyway.

Carry forwardCompression buys roughly one order of magnitude; growth eats it in a few years. Plan both.
Gorilla PDF mirror (canonical: vldb.org)
Paper Google2020-08

Monarch (VLDB 2020, cited from a mirror)

The ceiling of the arms race: close to a petabyte of compressed series in RAM, terabytes per second of ingest, 38 zones. What "just keep everything" actually costs at the limit.

Carry forwardIf your plan resembles Monarch and your budget does not, the funnel is not optional.
Monarch PDF mirror (canonical: vldb.org)
Paper Facebook2017-10

Canopy (SOSP 2017, cited from a mirror)

1.3 billion traces a day contained by edge sampling policies that carry an owner, a strategy, restraints and a lifetime, backed by global and per-tenant token buckets.

Carry forwardSampling at scale is policy with owners and expiry dates, not a constant in a config file.
Canopy PDF mirror (canonical: SOSP 2017)
Talk LightStep2018-12

Ben Sigelman, Three Pillars with Zero Answers (KubeCon NA keynote, slides)

Slide 11 gives the log cost equation; slide 12 draws Dapper's retention funnel, 100% to 0.01%; slide 24 prices cardinality as dollars per tag value.

Carry forwardPrice telemetry per tag value and per retained transaction, not per gigabyte, when arguing with a spreadsheet.
Slides PDF, GitHub mirror
Talk DigitalOcean2018-12

Tim Simmons, Adopting Prometheus the Hard Way (KubeCon NA, slides)

192 Prometheus servers, 200M+ series, 2M+ samples/s (slide 24), and the operational bound: queries should touch hundreds, not thousands, of series (slide 26).

Carry forwardSharding arrives at tens of millions of series per server; plan the shard key before the OOM chooses it for you.
Slides PDF, GitHub mirror
Talk VictoriaMetrics2025-09

Diana Todea, Cutting Through Metrics Cardinality Noise (SREday London, slides)

Practitioner root-cause list for cardinality cost (user_id, request_id, url, ip as labels, slide 10) and an over-collection worked example: "you're over-collecting by 12x" (slide 11).

Carry forwardAudit for the four usual-suspect labels first; they account for most explosions in the record.
Slides PDF, GitHub
Vendor Datadog2026 list

Pricing list and custom-metrics definition

The billing atom in writing: a custom metric is one name-and-tag-value combination including the host tag; $5 per 100 indexed per month against $0.10 per 100 ingested, and a 34x spread between indexed and Flex-stored log events.

Carry forwardThe 50x indexed-versus-ingested spread is the vendor telling you where they expect you to cut.
datadoghq.com/pricing/list
Vendor AWS2026-09-22

CloudWatch prices from the Price List API

Metric-months tiering $0.30 down to $0.02, logs at $0.50/GB ingest and $0.03/GB-month storage, pulled from the machine-readable price file with its own publication date.

Carry forwardQuote cloud prices from the Price List API, which timestamps itself, not from screenshots.
CloudWatch price file, us-east-1
Vendor Google Cloud2026

Cloud Observability pricing

Logging $0.50/GiB with 30 days included then $0.01/GiB-month; monitoring by ingested MiB tiering from $0.2580; managed Prometheus by the million samples, $0.06 tiering to $0.024.

Carry forwardGCP meters metrics by bytes and samples rather than series; the same workload prices differently per cloud, so model your own shape.
cloud.google.com/products/observability/pricing
Vendor Grafana Labs / Honeycomb / OneUptime2026

Vendor claims used with labels attached

Mimir's "1 billion active time series" is internal testing; Refinery's README documents dynamic sampling mechanics; OneUptime's ~$18,400/month worked bill is a competitor's list-price model. Each used here as a labelled claim, not a measurement.

Carry forwardVendor numbers show something was built and how it is priced; they never show how it went.
Mimir README
07

Build a miniature, then productionise it

Seven rungs from an evening's experiment to a priced, bounded pipeline. The crossing from toy to real happens at rung four.

Meter your own telemetry

Point promtool tsdb analyze (or your store's cardinality endpoint) at an existing setup and rank the top ten metrics by series count and the top ten label keys by distinct values.

Done when: you can name the three metrics that dominate your series count and who owns them.  Teaches: cardinality is measurable before it is billable.

Cause a cardinality explosion on purpose

In a sandbox Prometheus, add a label carrying a request ID to one metric and watch series count and memory climb; then set sample_limit on the scrape and watch the whole scrape fail instead.

Done when: you have seen both outcomes and the alert that fires (or fails to fire) for each.  Teaches: rejection semantics, and why the failed scrape is the honest failure mode.

Evict instead of reject

Configure an OTel SDK cardinality limit on the same workload and find the otel.metric.overflow series in the output; alert on its presence.

Done when: the overflow series appears under load and pages you.  Teaches: eviction semantics, and that the overflow series is containment's only witness.

Build the decision layer

Stand up an OTel Collector with a tail sampler biased to errors: keep every 5xx trace and roughly 1% of 2xx. Load it until the circular buffer starts dropping undecided traces, and record the memory-per-throughput slope while it does.

Done when: error traces survive a load test at 100% while 2xx traces sit near the target rate, and you know the RAM cost per thousand traces per second.  Teaches: the decision layer's economics, on the exact knobs the README warns about.

Split hot from cheap

Route the same log stream to an indexed store and, in parallel, to object storage or ClickHouse. Measure the per-gigabyte cost of each path and time a query against each tier.

Done when: you can state your own indexed-versus-archived cost spread and the query-latency price of the cheap tier.  Teaches: the two-price split from the inside.

Give tenants budgets

Run Loki or Mimir with per-tenant limits, drive one tenant past its stream or series cap, and verify the 429s land on that tenant while the neighbours stay healthy.

Done when: one tenant's overload is that tenant's problem, provably.  Teaches: blast-radius containment at the edge, the property every platform team is actually buying.

Price the whole thing

Take the series counts, gigabytes and span rates from rungs one to six and compute the monthly bill under Datadog, CloudWatch and GCP list prices; then compute the self-host cost including the inter-AZ replication traffic GitLab found dominating.

Done when: a one-page unit-economics sheet names your billing atom per signal and the utilisation at which each option flips.  Teaches: the argument you will actually have in the design review.

08

Keep hunting

The queries that found this material, grouped by what they surface. The last group is the workaround worth keeping: when a blog host is unreachable or dead, its static-site source repository often is not.

Production experience

  • "active time series" "churn rate"
  • "exclusion filter" logs cost "we"
  • "samples per second" "active series" migration
  • CaseStudies.md site:github.com metrics

The failure record

  • "cardinality explosion" postmortem OOM
  • site:gitlab.com gl-infra "incident review" mimir
  • "in-memory series" OOM ingester quorum
  • "monitors were unavailable" outage telemetry

The argument in the repos

  • repo:open-telemetry/opentelemetry-collector is:pr is:closed is:unmerged cardinality
  • "entire scrape will be treated as failed"
  • repo:prometheus/prometheus is:issue cardinality limit scrape
  • otel.metric.overflow stabilize

Prices, scale, and unreachable blogs

  • pricing.us-east-1.amazonaws.com offers AmazonCloudWatch index.json
  • "per metric-month" OR "per 100 custom metrics"
  • site:raw.githubusercontent.com <blog-name> content blog
  • <paper title> filetype:pdf site:raw.githubusercontent.com
09

References

  1. Datadog, 2023-03-08 Incident: Infrastructure connectivity issue affecting multiple regions Datadog blog, 2023-05-16. Checked 2026-09-23.
  2. Datadog, 2023-03-08 incident: A deep dive into the platform-level impact Datadog engineering blog, 2023-05-24. Checked 2026-09-23.
  3. Datadog, 2023-03-08 incident: A deep dive into our incident response Datadog engineering blog, 2023-06-01. Checked 2026-09-23.
  4. Datadog, Failure is inevitable: Learning from a large outage, and building for reliability in depth Datadog engineering blog, 2025-10-15. Checked 2026-09-23.
  5. Datadog status, Delayed Monitors Notifications (US1) status.datadoghq.com, 2026-09-21. Checked 2026-09-23.
  6. GitLab, Incident Review: 2020-04-22 Lack of Observability GitLab production-engineering tracker, 2020-04-22. Checked 2026-09-23.
  7. GitLab, 2022-01-27: Crashlooping Prometheus Pod GitLab production tracker, 2022-01-27. Checked 2026-09-23.
  8. GitLab, 2023-02-01: Some prometheus metrics are missing GitLab production tracker, 2023-02-01. Checked 2026-09-23.
  9. GitLab, Incident Review: Mimir unavailable GitLab production tracker, 2025-10-28. Checked 2026-09-23.
  10. GitLab, 2026-05-25: Mimir issues, grafana looks very sad GitLab production tracker, 2026-05-25. Checked 2026-09-23.
  11. GitLab, Work on Mimir cost optimization GitLab observability team tracker, 2024-02-13. Checked 2026-09-23.
  12. GitLab, Mimir production readiness review GitLab readiness repository, side-by-side since 2023-11. Checked 2026-09-23.
  13. token.place, Production relay metrics-cardinality OOM postmortem GitHub, 2026-09-03. Checked 2026-09-23.
  14. Zendesk (Mikhaylov, Hefty), Optimizing Datadog at scale: Cost-efficient observability at Zendesk Datadog blog (guest post), 2025-12-26. Checked 2026-09-23.
  15. Datadog (Artoul, Watt), Introducing Husky Datadog engineering blog, 2022-05-17. Checked 2026-09-23.
  16. Datadog (Krylysov, Lee), Timeseries Indexing at Scale Datadog engineering blog, 2024-06-28. Checked 2026-09-23.
  17. Netflix, Atlas documentation: Overview GitHub (atlas-docs), living document. Checked 2026-09-23.
  18. eBay (Samuel), Why and How eBay Pivoted to OpenTelemetry OpenTelemetry blog source, 2022-12-19. Checked 2026-09-23.
  19. Zerodha (Sharma), Logging at Zerodha zerodha.tech source repository, 2023-03-23. Checked 2026-09-23.
  20. Zerodha (Sharma), Infra monitoring at Zerodha zerodha.tech source repository, 2020-04-27. Checked 2026-09-23.
  21. VictoriaMetrics, Case studies and talks GitHub, living document. Checked 2026-09-23.
  22. Datadog, Case study: Nexthink datadoghq.com, undated. Checked 2026-09-23.
  23. Uber, M3 documentation: Motivation GitHub (m3db/m3), living document. Checked 2026-09-23.
  24. OpenTelemetry, OTEP 235: Sampling Threshold Propagation in TraceState GitHub, 2023. Checked 2026-09-23.
  25. OpenTelemetry, Tail Sampling Processor README GitHub, current main. Checked 2026-09-23.
  26. OpenTelemetry, tailsampling: Offloading trace storage to disk for scalability GitHub issue, 2025-08-28. Checked 2026-09-23.
  27. OpenTelemetry, Add cardinality_limit for the batch partitions (closed unmerged) GitHub pull request, opened 2026-04-29, closed 2026-09-17. Checked 2026-09-23.
  28. OpenTelemetry, Stabilize Overflow attribute section under Cardinality Limits GitHub issue, 2024-02-26. Checked 2026-09-23.
  29. Prometheus, Setting limits for maximum label value length GitHub issue, 2020-11-19. Checked 2026-09-23.
  30. Prometheus, Add cardinality_limit to scrape config GitHub issue, 2022-07-25, open. Checked 2026-09-23.
  31. Prometheus, Scrape configuration documentation GitHub, current main. Checked 2026-09-23.
  32. Prometheus, Proposal 0089: Query cost estimation and limits GitHub, 2025-2026, not implemented. Checked 2026-09-23.
  33. VictoriaMetrics, Series cardinality limiter semantics GitHub issue, 2025-07-31, open. Checked 2026-09-23.
  34. Grafana, Loki: Request validation and rate-limit errors GitHub, current main. Checked 2026-09-23.
  35. Grafana, Mimir README GitHub, current main. Checked 2026-09-23.
  36. Honeycomb, Refinery README GitHub, current main. Checked 2026-09-23.
  37. Google (Sigelman et al.), Dapper, a Large-Scale Distributed Systems Tracing Infrastructure Google technical report, April 2010. Checked 2026-09-23.
  38. Facebook (Pelkonen et al.), Gorilla: A Fast, Scalable, In-Memory Time Series Database VLDB 2015; cited from a GitHub mirror of the VLDB PDF. Checked 2026-09-23.
  39. Google (Adams et al.), Monarch: Google's Planet-Scale In-Memory Time Series Database VLDB 2020; cited from a GitHub mirror of the VLDB PDF. Checked 2026-09-23.
  40. Facebook (Kaldor et al.), Canopy: An End-to-End Performance Tracing And Analysis System SOSP 2017; cited from a GitHub mirror. Checked 2026-09-23.
  41. Sigelman (LightStep), Three Pillars with Zero Answers: A New Observability Scorecard KubeCon NA keynote slides, 2018-12-11; GitHub mirror. Checked 2026-09-23.
  42. Simmons (DigitalOcean), Adopting Prometheus the Hard Way KubeCon NA 2018 slides; GitHub mirror. Checked 2026-09-23.
  43. Todea (VictoriaMetrics), Cutting Through Metrics Cardinality Noise SREday London slides, 2025-09-18; GitHub. Checked 2026-09-23.
  44. Datadog, Pricing list datadoghq.com, 2026 list prices. Checked 2026-09-23.
  45. Datadog, Custom metrics billing docs.datadoghq.com. Checked 2026-09-23.
  46. AWS, Price List API: AmazonCloudWatch, us-east-1 Published 2026-09-22. Checked 2026-09-23.
  47. Google Cloud, Observability pricing cloud.google.com; logging price effective 2024-10-01. Checked 2026-09-23.
  48. OneUptime, The Real Cost of Observability in 2026 Competitor-vendor blog source, 2026-03-17. Checked 2026-09-23.