DEV Community

Cover image for SigNoz: The Open-Source Observability Platform That Actually Replaces Datadog
Syed Anzar
Syed Anzar

Posted on

SigNoz: The Open-Source Observability Platform That Actually Replaces Datadog

SigNoz: The Open-Source Observability Platform That Actually Replaces Datadog

You've probably heard "SigNoz is the open-source Datadog alternative" in every other dev post. But most explanations stop at "it uses OpenTelemetry and ClickHouse" -- as if that explains why it works.

It doesn't.

The real difference isn't the tech stack. It's how SigNoz solves the fundamental problem every observability platform faces: how to store and query logs, metrics, and traces together without melting your infrastructure or your budget.

The Problem Everyone Lives With

If you've used Datadog, New Relic, or any major SaaS observability platform, you know the drill:

  • Logs go to one system (Elasticsearch, Loki, CloudWatch)
  • Metrics go to another (Prometheus, Datadog metrics, InfluxDB)
  • Traces go to a third (Jaeger, Zipkin, Tempo)
  • Correlation happens in your head -- you switch tabs, copy trace IDs, pray the timestamps align

This isn't an accident. It's the natural consequence of how these systems evolved. Logs need full-text search. Metrics need time-series aggregation. Traces need span trees and latency percentiles. Three different query patterns. Three different storage engines.

Datadog solves this by charging you for three different products and gluing them together in the UI. You pay per host, per custom metric, per log ingested, per trace retained. The bill grows faster than your traffic.

SigNoz takes a different bet: one columnar database for everything.

Why ClickHouse Changes the Game

ClickHouse isn't just "fast." It's a column-oriented OLAP database built for analytical queries over massive datasets. Here's why that matters for observability:

One Query Language for All Signals

In SigNoz, a trace, a log line, and a metric live in the same database. You can write a single SQL query that joins spans with logs and aggregates metrics:

-- Find all errors in the payment service, show related logs, and calculate error rate
SELECT
    toDateTime(ts_bucket_start) as time,
    countIf(has_error = 1) as error_count,
    count() as total_spans,
    error_count / total_spans as error_rate
FROM signoz_index_v3
WHERE service_name = 'payment-service'
  AND ts_bucket_start >= now() - INTERVAL 1 HOUR
GROUP BY time
ORDER BY time DESC
Enter fullscreen mode Exit fullscreen mode

Try doing that across Elasticsearch + Prometheus + Jaeger. You can't. You'd need application-level correlation, which means more code, more latency, more things to break.

High-Cardinality Without the Tax

This is the killer feature nobody talks about.

In Prometheus/Datadog, every unique label combination creates a new time series. Add request_id, user_id, session_id to your metrics and you've created a cardinality explosion. Your bill explodes. Your query latency explodes. You're told "don't do that."

In ClickHouse, high-cardinality attributes live in typed Map columns. They're compressed with ZSTD. They don't create new time series. You can filter by user_id across billions of spans. It just works.

SigNoz takes this further: hot attribute keys get promoted to materialized columns automatically. The system adapts to your query patterns.

Compression That Actually Matters

ClickHouse uses per-column codecs tuned for observability data:

Data Type Codec Why It Works
Timestamps DoubleDelta Monotonic increasing = tiny deltas
Strings (labels, trace IDs) ZSTD Dictionary + entropy coding
Metric values (latencies, counts) Gorilla XOR-based floating-point compression
Integers (durations, counts) T64 Variable-byte encoding

Typical observability datasets compress 10-20x. That's not marketing -- it's columnar storage doing what it was designed for.

The Architecture: Three Planes, Not Five Microservices

SigNoz used to ship five separate containers: query-service, frontend, alertmanager, otel-collector, ClickHouse. That was v0.75 and earlier.

Since v0.76 (March 2025), it's three components:

+---------------------------------------------------------------+
|                    SigNoz Binary (single Go binary)           |
|  +----------+ +----------+ +----------+ +------------------+  |
|  |  React   | |  API     | |  Ruler   | |  Alertmanager    |  |
|  |  UI      | |  Server  | |  (alerts)| |  (notifications) |  |
|  +----------+ +----------+ +----------+ +------------------+  |
|                        |                                     |
|                  +-----+-----+                               |
|                  |  OpAMP    | <-- Manages collector config  |
|                  |  Server   |                               |
|                  +-----------+                               |
+---------------------------------------------------------------+
                              |
                              v
+---------------------------------------------------------------+
|              SigNoz OTel Collector (ingestion plane)          |
|  OTLP gRPC/HTTP * Jaeger * Zipkin * Prometheus * Kafka       |
|  Custom processors: span metrics, span mapper, LLM pricing   |
+---------------------------------------------------------------+
                              |
                              v
+---------------------------------------------------------------+
|                      ClickHouse (+ Keeper/ZooKeeper)          |
|  signoz_traces * signoz_logs * signoz_metrics * signoz_meter |
|  Resource fingerprint tables for fast filtering              |
+---------------------------------------------------------------+
Enter fullscreen mode Exit fullscreen mode

The Ingestion Plane: SigNoz OTel Collector

This isn't a vanilla OpenTelemetry Collector. It's a curated distribution with SigNoz-specific components:

Receivers: OTLP (gRPC 4317, HTTP 4318), Jaeger, Zipkin, Prometheus, Kafka, OpenCensus, HTTP logs (Heroku, JSON)

Processors that matter:

  • signozspanmetrics/delta -- computes RED metrics (Rate, Errors, Duration) from spans automatically. No separate metrics pipeline needed.
  • signozspanmapper -- normalizes framework-specific attributes (LangChain, LlamaIndex, etc.) into standard gen_ai.* semantic conventions
  • signozllmpricing -- multiplies token counts by per-model prices, writes cost attributes per span
  • batch -- 50k spans / 5 seconds (ClickHouse best practice: large, infrequent inserts)

Exporters: ClickHouse (traces, logs, metrics, meter), metadata exporter (drives query builder autocomplete)

Connector: signozmeter -- counts ingested volume per service/environment/host, powers usage dashboards

Extension: OpAMP health check + managed config. The collector connects to the OpAMP server inside the SigNoz binary, receives its config remotely, and applies it without redeployment. Log pipelines, span mapper rules, LLM pricing -- all editable in the UI.

The Storage Plane: ClickHouse Schema Design

This is where most observability platforms struggle. SigNoz's schema is worth understanding because it explains the query performance.

Traces (signoz_index_v3) and Logs (logs_v2) share the same layout:

Main table:           Resource table (companion):
+-----------------+   +---------------------------+
| ts_bucket_start |   | resource_fingerprint (PK) |
| resource_fp ----+-->| labels (string map)       |
| trace_id        |   | seen_at_ts_bucket_start   |
| span_id         |   +---------------------------+
| duration_nano   |
| has_error       |
| ...attributes...|
+-----------------+
Enter fullscreen mode Exit fullscreen mode

Resource attributes (service.name, k8s.namespace.name, deployment.environment) are hashed into a resource_fingerprint. The fingerprint is stored once per time bucket in the companion table. The main table only carries the fingerprint + timestamp bucket.

Query execution:

  1. Filter resource table by attributes (e.g., service.name = 'payment-service')
  2. Get matching fingerprints
  3. Scan main table granules: resource_fingerprint GLOBAL IN (...) + ts_bucket_start range

This is why SigNoz docs tell you to always filter on resource attributes first. Without a resource filter, you scan all granules. With it, you scan only the relevant ones.

Metrics (signoz_metrics_v2) use a different layout optimized for time-series: metric name + labels as columns, value + timestamp. PromQL and ClickHouse SQL both work.

TTL strategy: Daily partitions, ttl_only_drop_parts = 1. Retention drops whole parts (15 days for logs/traces, 30 days for metrics) -- no row-level deletes, no merge overhead.

What You Actually Get: Feature Walkthrough

APM That Works Out of the Box

Instrument your app with OpenTelemetry (auto-instrumentation exists for Java, Python, Node, Go, .NET, PHP, Ruby). Send to SigNoz OTel Collector. You get:

  • Service map with latency/error/throughput per service
  • Top endpoints with p50/p90/p99 latency, error rate, Apdex
  • Database calls, external calls, message queue spans -- all correlated
  • No dashboard building required. The APM views are generated from span data.

Logs That Correlate With Traces

Click a trace span -> see all logs with the same trace_id. Click a log -> jump to its trace. This works because both share the resource fingerprint + time bucket layout. No separate correlation engine needed.

Metrics From Spans (No Separate Pipeline)

The signozspanmetrics processor computes delta-temporality histograms and call counts per service/operation every 60 seconds. Dimensions: service.namespace, deployment.environment, service.version. Your APM dashboards are powered by span-derived metrics -- you don't need a separate Prometheus scrape setup for RED metrics.

LLM/AI Observability Built In

Since v0.143, the collector includes:

  • signozspanmapper -- normalizes input.value, gen_ai.prompt -> standard gen_ai.input.messages / gen_ai.output.messages
  • signozllmpricing -- reads gen_ai.usage.*_tokens, multiplies by model prices (pushed via OpAMP), writes signoz.gen_ai.usage.*.cost

You get token usage, latency, cost per request, model breakdown -- all in the same traces view.

Alerting That Doesn't Require a Separate Stack

The ruler (inside the SigNoz binary) evaluates alert rules on a schedule. Queries run against ClickHouse. Alertmanager handles deduplication, grouping, notification routing (Slack, PagerDuty, OpsGenie, webhook, email). Threshold, anomaly, and Apdex-based alerts all supported.

Dashboards: Query Builder, PromQL, or Raw ClickHouse SQL

Three query modes:

  1. Query Builder -- visual, no-code, generates ClickHouse SQL
  2. PromQL -- for Prometheus migrants, runs via ClickHouse's PromQL-compatible engine
  3. ClickHouse SQL -- full power for complex joins, cross-signal correlation

Dashboard panels can mix all three. Variables, templating, drill-downs -- standard fare.

Deployment: From Laptop to Production

Local (Docker Compose)

git clone https://github.com/SigNoz/signoz.git
cd signoz/deploy/docker/clickhouse-setup
./install.sh
# UI at http://localhost:8080
Enter fullscreen mode Exit fullscreen mode

Bare Metal (systemd via Foundry)

# Foundry = declarative CLI for self-hosted SigNoz
# One config provisions infra, installs backend, sets up OTel collection
foundry apply -f config.yaml
Enter fullscreen mode Exit fullscreen mode

Supports Docker, Swarm, systemd, Kubernetes, ECS, bare metal. Single binary + ClickHouse + Keeper.

Kubernetes (Helm)

helm repo add signoz https://charts.signoz.io
helm install signoz signoz/signoz -n platform
Enter fullscreen mode Exit fullscreen mode

Production: replicated ClickHouse (3+ shards), 3-node Keeper ensemble, PostgreSQL metastore, multiple SigNoz replicas behind ingress.

SigNoz Cloud

Fully managed. 30-day free trial, usage-based pricing starting at $49/month. SOC 2 Type II, HIPAA, RBAC, SSO, BYOC option.

The Trade-offs (Be Honest)

SigNoz isn't magic. Here's what you're signing up for:

Advantage Cost
No vendor lock-in -- OpenTelemetry native, your instrumentation is portable You operate ClickHouse -- need fast local disks (NVMe), CPU for merges, Keeper/ZooKeeper quorum
Predictable pricing -- no per-host, per-custom-metric, per-user-seat fees Schema migrations -- upgrades require running the migrator job, occasional breaking changes
Single database for all signals -- cross-signal correlation in SQL Operational complexity -- more moving parts than a SaaS dashboard
High-cardinality friendly -- filter by user_id, request_id freely Metrics cardinality still costs -- unbounded labels on metrics create time series
Self-hostable on bare metal -- no Docker/K8s required Foundry learning curve -- new tool, replaces raw Compose files since v0.130

The AGPL collector matters: The OTel Collector distribution is AGPL-3.0. If you modify and redistribute it, you must open-source your changes. Running it unmodified? No issue. Building a managed service on top? Talk to a lawyer.

When SigNoz Makes Sense

  • You're already on OpenTelemetry or willing to adopt it (vendor-free instrumentation)
  • You want correlated logs/metrics/traces without stitching three SaaS products
  • High-cardinality attributes are part of your debugging workflow
  • You have infrastructure capacity (or budget for managed Cloud) to run ClickHouse
  • You prefer SQL/PromQL over proprietary query languages

When to Stick With Datadog/New Relic

  • You only need infrastructure monitoring (host maps, cloud integration depth)
  • You don't want to operate a database -- SaaS wins on operational simplicity
  • You need Log Patterns / anomaly detection on logs -- SigNoz doesn't have this yet (roadmap)
  • Your team is small and observability isn't a core competency

Quick Start: Instrument a Go Service in 5 Minutes

// main.go
package main

import (
    "context"
    "net/http"
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
    "go.opentelemetry.io/otel/sdk/resource"
    "go.opentelemetry.io/otel/sdk/trace"
    semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
)

func initTracer() (*trace.TracerProvider, error) {
    exporter, err := otlptracehttp.New(context.Background(),
        otlptracehttp.WithEndpoint("localhost:4318"),
        otlptracehttp.WithInsecure(),
    )
    if err != nil {
        return nil, err
    }

    tp := trace.NewTracerProvider(
        trace.WithBatcher(exporter),
        trace.WithResource(resource.NewWithAttributes(
            semconv.SchemaURL,
            semconv.ServiceName("go-demo"),
            semconv.DeploymentEnvironment("development"),
        )),
    )
    otel.SetTracerProvider(tp)
    return tp, nil
}

func main() {
    tp, _ := initTracer()
    defer tp.Shutdown(context.Background())

    http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
        ctx, span := otel.Tracer("go-demo").Start(r.Context(), "hello-handler")
        defer span.End()

        // Simulate work
        span.AddEvent("processing")
        w.Write([]byte("Hello, SigNoz!"))
    })

    http.ListenAndServe(":8080", nil)
}
Enter fullscreen mode Exit fullscreen mode

Run SigNoz locally (./install.sh in the docker compose dir), run this service, hit /hello a few times. Open http://localhost:8080 -> Traces -> go-demo. You'll see the span, latency, and if you add logs, they'll correlate automatically.

The Bigger Picture

SigNoz represents a shift in how observability is built: open standards + columnar storage + unified query layer instead of proprietary agents + fragmented storage + per-signal pricing.

The industry is moving toward OpenTelemetry anyway. Datadog, New Relic, Grafana, Splunk -- all support OTLP ingestion now. But they still charge you for the storage and query layer they built around it.

SigNoz says: the storage and query layer should be open too.


Repository: github.com/SigNoz/signoz (32k+ stars)
Docs: signoz.io/docs
Slack: signoz.io/slack
Try Cloud: signoz.io/teams (30-day free trial)

Tags: opensource, observability, opentelemetry, clickhouse, datadog-alternative, selfhosted

Top comments (0)