Skip to content

Architecture

LinkMesh is a control plane for your OpenTelemetry collectors. You configure pipelines once in the UI; LinkMesh delivers the resulting collector config to every host that should run it, watches each collector’s health, and shows you what each one is actually doing.

Your telemetry never travels through LinkMesh. Collectors send data direct to your observability backends — Loki, Prometheus, Tempo, Grafana Cloud, Kafka, whatever you point them at.

How it all connects

SOURCES BACKENDS MANAGEMENT Logs Metrics Traces Loki Prometheus Kafka OPENTELEMETRY Collectors LinkMesh Server CONTROL PLANE
Telemetry flows from your sources through the collectors to your backends. The LinkMesh Server manages the collectors over a separate control-plane connection — it never sees your telemetry.

Three things move between the boxes:

  • Telemetry (solid arrows) — logs, metrics, and traces flow from your sources through the collectors to your backends.
  • Management (dashed line) — the LinkMesh server delivers config to, and receives health, status, and metrics from, every collector it manages.
  • Nothing else — no telemetry round-trips through the server, no outbound phone-home from the binaries.

The components

ComponentWhat it doesWhere it runs
LinkMesh ServerWeb UI, REST + gRPC API, OpAMP server, config store. The thing you log into.One instance per environment (VM or Kubernetes).
OpenTelemetry CollectorThe runtime that actually receives, processes, and exports telemetry. Runs one of two upstream runtimes — Grafana Alloy (config via remotecfg) or otelcol-contrib supervised by opampsupervisor (config via OpAMP).One per managed host, or per Kubernetes pod / DaemonSet.
LinkMesh Agent (optional)An edge connector for onboarding — it discovers the services and log sources on a host (pods, namespaces, and workloads on Kubernetes) and feeds them into the onboarding wizard so you configure the collector from what’s really there. It produces no telemetry, is not in the config path, and is not a collector.Alongside a collector, only when you want discovery-assisted onboarding.

The collector is the unit that always exists on a managed target. The agent is a separate, optional helper — see The agent.

The two collector runtimes

A collector runs one of two runtimes. Both are upstream binaries — LinkMesh ships no collector distribution of its own. Once configured a collector behaves the same either way; only how it receives its config differs.

Grafana Alloy — config via remotecfg (pull)

Alloy polls the LinkMesh server for its pipeline config over Bearer-authenticated HTTPS and pushes its own internal metrics back as OTLP. Use this runtime when you want a single, self-contained collector binary that fetches its own config.

CONTROL PLANE · remotecfg · Bearer HTTPS LinkMesh Server your hosted instance remotecfg + OTLP endpoint :8080 HTTPS · Bearer config pull · own_metrics push Grafana Alloy upstream · pulls config via remotecfg remotecfg poll · ~60s own_metrics OTLP push bootstrap config.alloy New config + hash (poll response) remotecfg GET poll · own_metrics OTLP DATA PLANE · OTLP logs · metrics · traces Your Observability Backends Loki · Tempo · Prometheus · Grafana Cloud · …

otelcol-contrib + OpAMP — config via push

An upstream otelcol-contrib supervised by upstream opampsupervisor connects to the LinkMesh server over OpAMP (WebSocket Secure); the server pushes remote config and the supervisor applies it. Use this runtime when you’re standardising on the OpenTelemetry OpAMP ecosystem.

CONTROL PLANE · OpAMP LinkMesh Server your hosted instance OpAMP Server endpoint /api/v1/opamp transport WSS · port 443 OpenTelemetry Collector otelcol-contrib + opampsupervisor :4317 OTLP / gRPC :4318 OTLP / HTTP :8888 own metrics RemoteConfig · Connection Settings EffectiveConfig · Health · Status DATA PLANE · OTLP logs · metrics · traces Your Observability Backends Loki · Tempo · Prometheus · Grafana Cloud · …

Pick per collector based on which ecosystem you’re standardising on — both are first-class, and a single LinkMesh server manages a mix of them.

The optional onboarding agent

Neither runtime needs the LinkMesh agent. The agent is a separate, optional edge connector: run it alongside a collector when you want LinkMesh to discover what’s worth collecting — running services and log sources on a VM, or pods, namespaces, and workloads on Kubernetes — and surface that into the onboarding wizard. It never carries telemetry and never delivers collector config. Full detail on the agent page.

How data flows through a pipeline

Inside a single pipeline, telemetry flows through a fixed sequence of stages. The meters on either end of the chain are what the UI shows you for “in” and “out” volume per pipeline.

flowchart LR
    S[Source] --> IM[Input meter]
    IM --> SF[Stream filters]
    SF --> P[Processors]
    P --> OM[Output meter]
    OM --> D[Destination]

    classDef io fill:#eef4ff,stroke:#1E63FF,stroke-width:2px,color:#0b1b3a;
    classDef stage fill:#ffffff,stroke:#94a3b8,stroke-width:1.5px,color:#0b1b3a;
    classDef meter fill:#f8fafc,stroke:#06B6D4,stroke-width:1.5px,color:#0b1b3a;
    class S,D io;
    class SF,P stage;
    class IM,OM meter;
  • Stream filters decide whether a record continues — drop noisy logs, sample traces, rate-limit per service.
  • Processors modify records that pass — mask PII, add labels, batch.
  • Meters are read-only — they count what entered and what left, so the UI can show you the throughput delta a pipeline produced.

See Pipeline for the full reference, or Build your first pipeline for a walkthrough.

How config reaches your hosts

When you save a change in the UI, this is what happens on the wire. The first three steps are identical for both runtimes; the last few differ because each runtime fetches/receives config its own way.

sequenceDiagram
    autonumber
    actor You as Operator
    participant UI as LinkMesh UI
    participant Srv as LinkMesh Server
    participant Repo as Config (Git-backed)
    participant Alloy as Alloy (remotecfg)
    participant Supervisor as opampsupervisor
    participant Col as otelcol-contrib

    You->>UI: Save pipeline change
    UI->>Srv: POST /api/v1/pipelines/...
    Srv->>Repo: Commit new YAML

    rect rgba(30, 99, 255, 0.06)
    Note over Alloy,Srv: Alloy runtime — collector PULLS via remotecfg
    Alloy->>Srv: GET /api/v1/remotecfg (poll, Bearer auth)
    Srv-->>Alloy: New River config + hash
    Alloy-->>Srv: Status + own_metrics (OTLP /v1/metrics)
    end

    rect rgba(6, 182, 212, 0.06)
    Note over Supervisor,Col: otelcol + OpAMP runtime — server PUSHES via OpAMP
    Srv->>Supervisor: OpAMP RemoteConfig (over WSS)
    Supervisor->>Col: Restart with effective.yaml
    Col-->>Supervisor: Health + effective config
    Supervisor-->>Srv: EffectiveConfig + status
    end

    Srv-->>UI: Live status update

Three things worth knowing:

  • A save is durable as soon as step 3 succeeds. If a collector is offline, it picks up the new config when it reconnects — Alloy on its next poll, OpAMP on its next session.
  • The collector reports back what config it actually loaded (steps 6 / 11). The UI compares that to what was committed; mismatches show up as a “drift” badge on the collector.
  • The optional onboarding agent doesn’t appear here at all — it’s not in the config path. Config flows directly between the collector and the server (Alloy via remotecfg, otelcol via OpAMP). When present, the agent only helps you discover what to collect during onboarding; it never sees config bytes.

Where your data lives

Three different stores, each with a different lifetime and purpose:

flowchart TB
    subgraph Srv["LinkMesh Server"]
        Cfg[(Config repository<br/>Git-backed YAML)]
        Run[(Runtime state<br/>collector status, metrics, events)]
    end

    subgraph Host["Each managed host"]
        Local[(Collector config<br/>on local disk)]
    end

    Cfg -- "delivered on change" --> Local
    Local -- "status + health" --> Run
  • Config repository — the source of truth for what every collector should be running. Versioned, auditable, restorable. Survives any server restart.
  • Runtime state — live operational data: which collectors are connected, last-seen timestamps, recent throughput, recent errors. Rebuilds itself from collector heartbeats if lost. This lives in the server’s storage backend — an embedded BoltDB database by default, or an external MongoDB database for high-availability deployments.
  • Local collector config — a cached copy of what the server most recently delivered. The collector reads from here on startup, which is why collectors keep running across LinkMesh server restarts.

Your telemetry data itself is never stored by LinkMesh. It moves through the collector and out to your backends; LinkMesh only sees the counters.

Data-handling guarantees

LinkMesh is on-premises by design: telemetry stays inside customer infrastructure, and product binaries don’t phone home. The architectural implications for a security review live on the marketing site — Trust on linkmesh.io lays out the data-handling story with verifiable, plain-language claims.