Observability bills are usage-based, per host, per GB ingested, per module, and they compound with every host, custom metric, and high-cardinality tag. Teams with engineering capacity move to open stacks (Prometheus + Grafana, Loki for logs, Tempo for traces; or Zabbix/Elastic) and cut spend sharply, trading SaaS polish for operational ownership.
Know what you’re replacing
Commercial suites bundle several products. Map each before starting: infrastructure metrics → Prometheus/OpenTelemetry; dashboards → Grafana; monitors/alerts → Prometheus rules + Alertmanager; logs → Loki or Elasticsearch/OpenSearch; APM/traces → Tempo/Jaeger; synthetics/RUM → separate tooling. The honest gap is cross-signal correlation and UX, achievable, but you own the integration.
What retention and cardinality will cost you
Bills are largely per monitored host plus ingest. Self-hosting shifts cost to compute + storage + engineering time, usually far lower at scale, but not zero. Retention and cardinality are what made the incumbent expensive; they’ll size your Prometheus/Mimir and Loki storage too, so set them deliberately and use recording rules.
Migration flow
Inventory dashboards, monitors, retention, and paging integrations (export via API). Stand up the stack (the kube-prometheus-stack Helm chart is a common start) and roll out exporters/agents. Recreate the monitors that page humans first, rebuild top dashboards, then dual-run to compare coverage and false-positive rates. Cut over paging (Alertmanager → PagerDuty/Opsgenie) last.
The real shift: query language
PromQL is a different model from the incumbents’ query languages, rate calculations, histogram_quantile, label matching, recording rules. Budget time for on-call engineers to get fluent; alert quality depends on it. The logging side has its own language too: Loki’s LogQL selects a few stable labels and then filters the raw lines, so searches that leaned on heavily indexed, high-cardinality fields (as Splunk’s SPL allowed) need reshaping, not a straight port. Traces add TraceQL. Plan for the fact that one incumbent query language usually becomes two or three open ones.
Picking a target stack
The right destination depends on what the incumbent was really doing for you. For metrics-centric estates, a Prometheus + Grafana core is the default, extended with Thanos or Mimir for long retention. If you want the unified metrics-logs-traces experience a suite like Datadog or Dynatrace gave you, the full Grafana stack (Mimir, Loki, Tempo under one Grafana UI) is the closest single-pane replacement, self-hosted or as Grafana Cloud. Log-heavy Splunk estates map to Grafana + Loki, with the caveat that premium tiers like Enterprise Security and ITSI need a separate plan (an open SIEM such as Wazuh or Elastic). Network and infrastructure polling from SolarWinds maps to Zabbix, where you template once and scale with discovery and proxies rather than paying per node and per module. Instrument new services with OpenTelemetry wherever possible; it is vendor-neutral and feeds all of these backends from one layer.
What doesn’t port cleanly
Set expectations early. Auto-instrumentation breadth (the Datadog agent, New Relic’s language agents, Dynatrace OneAgent) is the hardest thing to reproduce; with OpenTelemetry you enable coverage per language and add manual spans for bespoke code. Vendor “AI” features such as Dynatrace’s Davis auto-RCA have no free open equivalent, Grafana alerting is rule-based and you define the conditions. Real-user monitoring and synthetics have thinner OSS coverage. And correlated pivoting from a metric to its logs and traces takes wiring through shared labels and trace IDs rather than arriving for free.
Run both stacks until paging is proven
Fire test alerts end-to-end (trigger → Alertmanager → pager → ack), do a dashboard-parity review, and run a retention/scale load test. The acceptance bar is “we get paged correctly for the incidents we care about.” Keep the incumbent running until that’s proven.
Open a source→target page for stack-specific steps and a per-host TCO model.