Synadia Insights

Configuration

Insights uses a layered configuration system. Every setting can be specified through CLI flags, environment variables, or a YAML config file.

Priority Order

When the same setting is defined in multiple places, the highest-priority source wins:

  1. CLI flags (e.g., --server nats://host:4222)
  2. Environment variables (e.g., INSIGHTS_NATS_SERVER=nats://host:4222)
  3. YAML config file (via --config, INSIGHTS_CONFIG, or a default search path; see Config File)
  4. Built-in defaults

Config File

--config (or -c) is a global flag, so every subcommand can be driven from one file, not just the server. This matters with the default embedded NATS sink: the server serves its API on sink.port, and insights db query reaches it via the top-level nats: section. Pin both in one file and point every command at it:

# config.yaml
sink:
  port: 4222 # server binds the embedded NATS here
nats:
  server: nats://127.0.0.1:4222 # clients (query, checks, ops, ...) connect here
insights -c config.yaml              # run the server
insights db query -c config.yaml "SELECT 1"   # query it — no --server needed

The config file is found from three sources, each optional, in increasing precedence (later wins):

  1. <user-config-dir>/insights/config.yaml: e.g. ~/.config/insights/config.yaml on Linux, ~/Library/Application Support/insights/config.yaml on macOS.
  2. ./insights.yaml: auto-discovered in the working directory.
  3. INSIGHTS_CONFIG: an explicit path set via the environment.

An explicit --config/-c flag overrides all of these. With a file at one of the default locations, a bare insights db query "SELECT 1" works with no flags. Per-setting environment variables (INSIGHTS_*) still override any config file (see Priority Order).

./insights.yaml is read from the current working directory, so any directory you run insights from can supply configuration (as with git, cargo, and similar tools). Avoid running insights from untrusted or world-writable directories, or pass --config explicitly. CLI flags and INSIGHTS_* environment variables always override the file.

Keys the configuration does not define are ignored without a warning, and insights config check does not report them either, so a misspelled or removed key leaves its setting at the default. Compare a file against the sections below when a value seems to have no effect.

An annotated example of every option with its default:

# Insights Configuration Example
#
# This file shows all available configuration options with their defaults.
#
# Loading this config (any subcommand, not just the server):
#   - insights -c config.yaml            (explicit flag, highest precedence)
#   - INSIGHTS_CONFIG=config.yaml insights ...
#   - place it at ./insights.yaml or <user-config-dir>/insights/config.yaml
#     to have it discovered automatically with no flag
# The top-level nats: section drives client subcommands (query, checks, ops, web, mcp, http, ...);
# pin sink.port and nats.server together so one file serves both sides.
#
# The collector (`insights-collector serve`) reads
# the same file but uses only the data-dir/node/system/sys/scraper/sink/license/
# updater/telemetry settings; the db/indexer/web/prometheus sections are inert
# there (there is no local database).
#
# Configuration priority (highest wins):
#   1. CLI flags (e.g., --server; --nats.server is a hidden alias)
#   2. Environment variables (e.g., INSIGHTS_NATS_SERVER)
#   3. Config file (this file)
#   4. Defaults
#
# The subsystem on/off switches below (scraper/indexer/web/simulator/prometheus/
# updater/telemetry `enabled:`) are spelled as bare shorthands outside this file --
# --web=false on the command line, INSIGHTS_WEB=false in the environment. In
# YAML the section is a map, so use its enabled: key as shown here.

# Log level: debug, info, warn, error
log-level: 'info'

# License configuration, for trial builds (the -licensed archives and the
# insights-licensed image). Provide either a raw JWT string or a path to a file
# containing the JWT. If both are set, the file takes precedence.
# A trial build requires it unless the simulator is enabled or the node runs
# neither the indexer nor the scraper. Other builds require no license; leave it
# empty there, since a license that is set is still verified at startup.
license:
  # Raw license JWT token string.
  # Env: INSIGHTS_LICENSE_TOKEN
  token: ''
  # Path to a file containing the license JWT.
  # Env: INSIGHTS_LICENSE_FILE
  file: ''

# Base directory for persistent storage (DuckDB database + JetStream data).
# If empty, a temporary directory is created and data is lost on restart.
# Set this for persistent deployments.
data-dir: ''

# Node identity: names this process for the node-scoped API space
# ($INS.node.<id>.ops.pprof, ...) and as a stable label for operator tooling.
# Defaults to the id of the single system this node serves, which survives a
# reschedule where the hostname would not. A node serving several systems must
# be named; a web node, serving none, falls back to the hostname sanitized to a
# subject-safe token. Allowed characters: letters, digits, '_', '-'.
node:
  # Env: INSIGHTS_NODE_ID
  id: ''
  # Operator-assigned labels describing where this process runs. They are
  # reported on $INS.ping, so `insights node list` and the web Nodes tab can
  # filter and group by them (`env=prod`). Nothing addresses a subject with
  # them and no behaviour keys off them. Keys allow letters, digits, '_', '-'
  # and '.'; values are free text without control characters. Max 16 pairs.
  # Set here rather than by flag or env — a map has no readable flag form.
  # metadata:
  #   region: us-east-1
  #   rack: b12

# System identity: names the monitored NATS system's API subtree
# ($INS.sys.<id>.db.query, ...). Operator-assigned — no stable NATS system
# identifier can be derived. Allowed characters: letters, digits, '_', '-'.
system:
  # Env: INSIGHTS_SYSTEM_ID
  id: 'default'
  # Operator-assigned labels describing the monitored system, on the same terms
  # as node.metadata above. Declared where the system is scraped: a node that
  # indexes a collector-fed system without scraping it refuses to start with
  # this set, because the collector is what describes the system. The
  # multi-system list below takes the same block per entry.
  # metadata:
  #   env: prod
  #   team: platform

# Multiple systems (optional). One instance can own several monitored systems,
# each with its own DuckDB instance, JetStream stream, and $INS.sys.<id>.* API.
# Set this list ONLY for a node monitoring more than one system; a single-system
# node — the usual deployment, a collector, a federated instance — uses the flat
# system:/sys:/scraper:/sink: config above and leaves this empty.
#
# systems: is mutually exclusive with system.id / sys / the flat scraper. A node with this list
# always indexes (indexer.enabled must be true), and cannot run the simulator.
# The top-level db: section becomes the per-system default; each entry overrides
# it.
#
# systems:
#   # Outbound scraper: this node both scrapes and indexes this system. A `scrape`
#   # block makes it scraped locally; omit it for a collector-fed system whose
#   # stream a NATS mirror fills.
#   - id: "core-prod"
#     scrape:
#       nats:
#         server: "nats://core.internal:4222"
#         creds: /etc/insights/core-prod.creds
#       interval: 20s          # falls back to scraper.interval
#       # timeout: 30s         # falls back to scraper.timeout
#     retention: 24h           # stream buffer depth (falls back to sink.retention); the DB keeps history
#     db:                      # per-instance DuckDB sizing (overrides the top-level db:)
#       memory-limit: "8GiB"
#     check-thresholds:        # per-system overrides, merged per code onto the top-level set
#       server-003:
#         cpu_percent: 80
#     metadata:                # labels for filtering and grouping; only on an entry with a scrape block
#       env: prod
#       team: platform
#     disabled-checks:         # unioned with the top-level list, never subtracted from it:
#       - account-012        # an entry can turn a check off, not back on
#   # Collector-fed: no scrape block. That is the whole declaration — this node
#   # creates the system's stream as a JetStream mirror of the one a collector
#   # fills, and only indexes it.
#   - id: "edge-west"
#     retention: 6h            # buffer depth, enforced by pruning whole epochs
#     #
#     # Nothing else is required. The stream is named "mirror_<id>", the origin
#     # is the collector's "scrape_<id>" — the same id, derived on both sides —
#     # and the collector is asked over $INS.sys.<id>.ops.sink.info for the names,
#     # subject prefix, domain and scrape cadence it actually uses.
#     #
#     # Set this only when the origin's JetStream is reached by something other
#     # than a domain — a subject mapping or an account import under a prefix of
#     # your choosing, which exists on this side and so cannot be discovered.
#     # mirror-api-prefix: "JS.edge-west.API"
#     #
#     # Stream shape. Every field is optional; name defaults to "mirror_<id>"
#     # here and "scrape_<id>" for a scraped system, and the sizing falls back to
#     # the top-level sink:. A mirror must not share its origin's name:
#     # $JS.FC.<stream>.> flow-control subjects are not domain-prefixed.
#     # stream:
#     #   name: "mirror_edge_west"
#     #   replicas: 3            # requires a clustered sink (sink.embed: false)
#     #   storage: "file"        # or "memory"

# Top-level NATS connection for serving the API.
# These credentials are used by the API server and as defaults
# for indexer and scraper if not explicitly configured.
nats:
  # NATS server URL
  server: ''
  # Path to credentials file (.creds)
  creds: ''
  # NATS context name (from nats context)
  context: ''
  # Username for basic auth
  user: ''
  # Password for basic auth
  password: ''
  # NKey seed for NKey+JWT auth (requires jwt to also be set)
  nkey: ''
  # User JWT for authentication.
  # If nkey is also set, used as NKey-signed JWT auth.
  # If standalone, used as a bearer token (server must have bearer_token enabled).
  jwt: ''
  # TLS certificate path
  tls-cert: ''
  # TLS key path
  tls-key: ''
  # TLS CA certificate path
  tls-ca-cert: ''
  # Perform TLS handshake first (before NATS protocol)
  tls-first: false
  # SOCKS proxy URL for connections
  socks-proxy: ''
  # Request/reply inbox prefix. Empty uses the NATS default (_INBOX).
  # Set this when the account is not granted _INBOX.>
  inbox-prefix: ''

# NATS system account credentials for the target system being scraped.
# This connection is used to issue $SYS requests to collect metrics.
# This is required if the simulator is disabled.
sys: {}

# Database configuration for DuckDB.
db:
  # DuckDB memory limit. Caps the buffer pool to prevent swapping on large databases.
  # Examples: "4GiB", "8GiB", "16GiB". Default: "4GiB".
  # Env: INSIGHTS_DB_MEMORY_LIMIT
  memory-limit: '4GiB'
  # DuckDB worker threads. 0 uses DuckDB's default (all cores).
  # Reduce to leave cores for the indexer and web server.
  # Env: INSIGHTS_DB_THREADS
  threads: 0
  # Max wall-clock time a single $INS.db.query statement may run before it is interrupted.
  # Guards against a pathological query (e.g. a count over a cartesian relation, which is pure
  # CPU and never trips the memory limit) pegging the server. 0 disables the cap.
  # Env: INSIGHTS_DB_QUERY_TIMEOUT
  query-timeout: 2m
  # Max rows the non-streaming $INS.db.query endpoint may return. That endpoint buffers the
  # whole result before responding, so an unbounded SELECT * could return enough rows to run
  # the server out of memory (the DuckDB memory_limit does not bound this buffered reply).
  # Oversized results are rejected with a 413 pointing at the streaming endpoint
  # $INS.db.query.stream. 0 disables the cap.
  # Env: INSIGHTS_DB_QUERY_MAX_ROWS
  query-max-rows: 100000
  # Streaming query endpoint ($INS.db.query.stream). Pushes results as windowed Arrow IPC
  # chunks (rendered to CSV/JSON client-side) so arbitrarily large results never accumulate
  # in memory on either side, so it is not subject to the query-max-rows cap
  # (it carries only the large query-stream.max-rows safety limit below).
  query-stream:
    # Max chunks kept in flight unacknowledged before the server pauses producing. Bounds
    # client-side buffering to roughly window × chunk-size.
    # Env: INSIGHTS_DB_QUERY_STREAM_WINDOW
    window: 16
    # Target size of each chunk message (IEC units). Clamped below the connection max_payload.
    # Env: INSIGHTS_DB_QUERY_STREAM_CHUNK_SIZE
    chunk-size: 512KiB
    # Max time to produce each Arrow batch (incl. the first), bounding a stalled or slow-to-
    # first-row query. 0 disables.
    # Env: INSIGHTS_DB_QUERY_STREAM_BATCH_TIMEOUT
    batch-timeout: 30s
    # Abort the scan if the client sends no acknowledgement within this window (dead/Ctrl-C'd
    # consumer). 0 disables.
    # Env: INSIGHTS_DB_QUERY_STREAM_ACK_IDLE_TIMEOUT
    ack-idle-timeout: 30s
    # Per-buffer Arrow IPC compression for streamed chunks: none, lz4, or zstd. Clients
    # decompress transparently. Compression uses additional CPU; leave none unless bandwidth
    # is the bottleneck.
    # Env: INSIGHTS_DB_QUERY_STREAM_COMPRESSION
    compression: none
    # Abort a streamed query after this many rows, failing fast with guidance to scope it.
    # Rows are counted as they are produced, so the cap bounds the work an unscoped SELECT *
    # over a per-epoch table/view (e.g. hx.conns, millions of rows across all history) can do
    # before it is stopped. Bounded queries (epoch-scoped, entity-scoped, or LIMITed) never
    # reach it. 0 disables the cap for operators who need very large exports.
    # Env: INSIGHTS_DB_QUERY_STREAM_MAX_ROWS
    max-rows: 1000000
  # Retention policy for automatic epoch cleanup from DuckDB.
  retention:
    # How long to keep data. 0 disables retention.
    # Env: INSIGHTS_DB_RETENTION_DURATION
    duration: 768h
    # Minimum time between retention sweeps. A sweep runs on the indexer right after
    # the first epoch committed past the interval, never concurrently with a commit.
    # Env: INSIGHTS_DB_RETENTION_INTERVAL
    interval: 10m
  # Live memory profiler: samples duckdb_memory() so `ops sizing` and
  # `ops memory` can use measured peaks instead of estimates.
  memory-profile:
    # Enable the background memory profiler.
    # Env: INSIGHTS_DB_MEMORY_PROFILE_ENABLED
    enabled: true
    # How often to sample duckdb_memory() (metadata-cheap).
    # Env: INSIGHTS_DB_MEMORY_PROFILE_INTERVAL
    interval: 2s
    # Rolling window retained in memory for the peak and the Realtime chart.
    # Env: INSIGHTS_DB_MEMORY_PROFILE_WINDOW
    window: 15m

# Scraper configuration for collecting metrics from NATS servers.
scraper:
  # Enable or disable the scraper
  enabled: true
  # Timeout for scrape requests
  timeout: 30s
  # Interval between scrapes
  interval: 1m
  # Optional NATS connection for publishing scraped data.
  # If not specified, uses the indexer NATS config (or top-level NATS).
  nats: {}
  # Optional filter controlling which discovered servers are scraped. Matching
  # is exact (by server name, cluster name, or tag). Deny takes precedence over
  # allow; when any allow list is set, a server must match it to be scraped.
  # Excluded servers receive no monitoring requests. Omit to scrape every
  # discovered server.
  filter:
    # Scrape only servers matching these. When all allow lists are empty, every
    # server not denied is scraped.
    allow:
      servers: []
      clusters: []
      tags: []
    # Never scrape servers matching these (takes precedence over allow).
    deny:
      servers: []
      clusters: []
      tags: []

# Indexer configuration for processing and storing scraped data.
indexer:
  # Enable or disable the indexer
  enabled: true
  # Start consuming from the latest message in the stream
  stream-latest: false
  # Start consuming from a specific epoch number
  stream-epoch: 0
  # Filter specific Z endpoints to process (comma-separated: varz,jsz,connz)
  stream-filters: ''
  # Downsample interval for consuming epochs
  stream-interval: 0s
  # Optional NATS connection for consuming scraped data.
  # If not specified, uses the top-level NATS config.
  nats: {}

# Sink configuration for the embedded NATS server.
sink:
  # Use an embedded NATS server for storing scraped data.
  embed: true
  # Optional NATS server config file for the embedded server.
  # The file is parsed first, then Insights-specific settings are applied on top.
  # config-file: /path/to/nats-server.conf
  # Host to bind the embedded NATS server to
  host: '127.0.0.1'
  # Port to bind the embedded NATS server to (0 = random)
  port: 0
  # JetStream stream name for storing scraped data.
  # The collector derives this from system.id ("scrape_<id>") when the id is
  # set and this is left at the default, so a central node mirroring the collector lands
  # on the same name without being told it.
  stream: 'scrape'
  # Batch size for sink operations
  batch-size: 500
  # How long to keep scraped data in the sink stream. 0 disables retention.
  # Enforced by pruning whole epochs, not by the stream's max age: a
  # message-level limit would leave the indexer a scrape truncated mid-epoch.
  # Env: INSIGHTS_SINK_RETENTION
  retention: 24h
  # Replica count for the sink stream. Requires a clustered sink — the embedded
  # server is a single node, and embed: true with replicas > 1 is rejected.
  # Env: INSIGHTS_SINK_REPLICAS
  replicas: 1
  # Storage class for the sink stream: "file" or "memory". The stream is a
  # buffer — the database holds the history — so memory storage is a reasonable
  # choice for a system that can afford to lose the buffer on restart.
  # Env: INSIGHTS_SINK_STORAGE
  storage: 'file'

# Embedded NATS simulator configuration.
# When enabled, starts real in-process NATS clusters with traffic workloads
# so you can try insights with zero configuration.
simulator:
  # Enable the embedded simulator
  enabled: false
  # Profiles: core-{small,medium,large}, js-{small,medium,large},
  #   super-{small,medium,large}, leaf-{small,medium,large},
  #   super-leaf-{small,medium,large}
  profile: 'js-small'

# Web server configuration for the Exo-based UI.
web:
  # Enable or disable the web server
  enabled: true
  # Hostname to bind the web server to
  hostname: '127.0.0.1'
  # Port to bind the web server to
  port: 8080
  # Session seed for secure cookies.
  # The default "insights" preserves sessions across restarts but should be
  # changed to a unique value for production deployments.
  session-seed: 'insights'
  # Enable TLS (HTTPS). When enabled, HTTP/2 is automatically available via ALPN.
  # Requires tls-cert and tls-key below; enabling TLS without them is an error.
  tls: false
  # Path to TLS certificate file.
  tls-cert: ''
  # Path to TLS private key file.
  tls-key: ''
  # Path to TLS CA certificate file for verifying client certificates.
  tls-ca-cert: ''
  # Public URL of this Insights instance, used in webhook alert payload links.
  # Env: INSIGHTS_WEB_EXTERNAL_URL
  external-url: ''

# Prometheus metrics endpoint configuration.
# Exposes check failure counts as Prometheus gauges for external scraping.
prometheus:
  # Enable or disable the Prometheus metrics endpoint
  enabled: true
  # Hostname to bind the Prometheus metrics server to
  hostname: '127.0.0.1'
  # Port to bind the Prometheus metrics server to
  port: 9091
  # Serve every node's metrics from this endpoint instead of only this node's.
  # Each scrape discovers the deployment's nodes over $INS.ping and asks each one
  # for its snapshot. Enable it on exactly one node: scraping two aggregators
  # reports every series twice, once per endpoint.
  # Env: INSIGHTS_PROMETHEUS_AGGREGATE
  aggregate: false
  # Budget for one aggregated collection: node discovery, then the per-node
  # requests. Must be shorter than the scrape timeout of whatever reads this
  # endpoint, or Prometheus gives up before the answer. Ignored unless aggregate.
  # Env: INSIGHTS_PROMETHEUS_TIMEOUT
  timeout: 2s

# Version checker configuration.
# When enabled, periodically checks GitHub for a newer release and notifies
# via log messages and a UI toolbar badge. Does not download or restart.
# The release repository is compiled into the binary, so there is no URL
# or channel to configure.
# For trial builds, the info dialog shows a direct download link for
# the current OS/architecture. Other builds direct users to
# purchases.synadia.com.
updater:
  # Enable or disable version checking
  enabled: true
  # Interval between update checks
  interval: 1h

# Product telemetry. A pulse every few minutes reporting how this instance is used, so a
# trial can be told apart from an install that was started once and forgotten.
# Only trial builds contain the code that sends it — every other build has no
# reporter at all, and these settings are inert there.
#
# What a pulse contains is listed in full in the reference documentation. In
# short: a random instance id generated here, the release version and platform,
# the scrape and pulse intervals, how large the watched environment is, and counts
# of pages opened in the web UI and requests made by the CLI, MCP and HTTP
# clients. It carries nothing about the monitored system
# itself — no server, cluster, account, subject, stream or consumer names, no
# addresses, no message data, no configuration values, no query text.
#
# The instance is identified only by the license it presents, so the payload
# contains nothing that names you.
# There is no destination setting: where a pulse goes, and the credential it is
# published with, are fixed when the binary is built. You can switch telemetry
# off, or read exactly what it would send, but not redirect it.
telemetry:
  # Enable or disable telemetry
  enabled: true
  # Interval between pulses; the first is sent at startup
  interval: 5m
  # Log every pulse, so you can read exactly what leaves this process
  print: false
# Notification endpoint definitions (optional, YAML-only — there is no equivalent
# flag or environment variable). Endpoints receive JSON payloads when subscribed
# check results change state (firing/resolved). Endpoints are read-only in the web
# UI; all configuration is done here.
#
# Two types are supported:
#   webhook:       Receives the full Payload envelope (status, alerts, groupLabels,
#                  etc.) — compatible with Alertmanager webhook_config receivers.
#   alertmanager:  Receives a bare []Alert array — compatible with the Alertmanager
#                  v2 POST /api/v2/alerts API.
#
# Both types share the same endpoint fields. Names must be unique across all types.
# A malformed endpoint (missing name/url, non-http(s) url, unknown auth-type, a
# duplicate name, or a systems entry naming a system this node does not own) fails
# startup with an error naming the offending entry — it is never silently skipped.
# Delivery uses a fixed 10s request timeout and 3 attempts with exponential backoff
# (1 attempt on a 4xx other than 429); a failed delivery is retried for that
# endpoint at up to one-minute intervals until it succeeds.
#
# subscriptions and ignore are lists of check-code patterns: an exact code
# (server-001), a trailing-wildcard prefix (server-*), or "*" for every code.
# ignore is applied after subscriptions, so it carves exceptions out of a
# wildcard. An empty subscriptions list delivers nothing — subscribing is
# explicit. A pattern that matches no known check code fails startup, so a typo
# never silently delivers nothing.
#
# systems is the inverse: an empty list delivers for every system this node owns,
# and a non-empty list scopes the endpoint to those systems (each must be one this
# node owns).
# Example (uncomment and adjust):
# notifications:
#   webhook:
#     - name: "PagerDuty Relay"
#       url: "https://example.com/webhook"
#       enabled: true
#       auth-type: ""          # "", "basic", "bearer", "hmac"
#       auth-user: ""          # username for basic auth
#       auth-token: ""         # password (basic), token (bearer), or secret (hmac)
#       subscriptions:         # check-code patterns to subscribe to (empty = deliver nothing)
#         - server-*
#         - stream-002
#       ignore:                # patterns to drop after a subscription match
#         - server-046
#       systems:               # systems to deliver for (empty = every system on this node)
#         - prod-us
#         - prod-eu
#   alertmanager:
#     - name: "Alertmanager"
#       url: "http://localhost:9093/api/v2/alerts"
#       subscriptions:
#         - "*"

# Per-check threshold overrides for the checks (optional, YAML-only — there
# is no equivalent flag or environment variable).
# Many checks accept tunable parameters (a CPU percentage, a lag percentage,
# a byte size, ...) that control when they produce a finding. Defaults suit most
# deployments; override only what you need, keyed by check code and parameter name.
# Run `insights checks list` for codes and `insights checks info <CODE>` for the
# parameters a check accepts. Duration parameters take Go duration strings (e.g.
# 50ms, 5m, 1h); one that bounds a window measured across scrapes must be >= the
# scrape interval. Size parameters take IEC binary strings (e.g. 64 KiB, 1 MiB,
# 10 GiB) or a bare number of bytes. Percentage parameters end in _percent and
# take a 0-100 value. An unknown parameter name or check code fails startup
# with an error naming it. A code in the uppercase, underscored form (SERVER_003)
# is reported with its current spelling, and a renamed parameter with its
# replacement; any other unknown code is reported as unknown.
# Example (uncomment and adjust):
# check-thresholds:
#   server-003:
#     cpu_percent: 80        # flag servers above 80% per-core CPU (default 90)
#   stream-002:
#     lag_percent: 20        # flag stream replica lag above 20% (default 10)
#   stream-022:
#     max_memory: 500 MiB    # flag memory-backed streams above 500 MiB (default 100 MiB)
#   # Optimization checks also accept `lookback`, the analysis window for
#   # range-based checks (default 6h):
#   account-011:
#     lookback: 4h

# Checks to turn off (optional, YAML-only — there is no equivalent flag or
# environment variable).
# A disabled check keeps running and stays visible, marked disabled, with its real
# findings. It is left out of the health grades and never delivered as a
# notification — no advisory, no webhook, no alert.
# Turn a check off when it cannot be acted on in this topology — a cross-cluster
# gateway traffic ratio is above any threshold by construction in a single-account
# supercluster — rather than to quiet a signal you would still want to see.
# A code matching no check fails startup with an error naming it; a code in the
# uppercase, underscored form (ACCOUNT_012) is reported with its current spelling.
# `insights config check` runs the same validation without starting the node.
# Example (uncomment and adjust):
# disabled-checks:
#   - account-012

Environment Variable Naming

Every flag has a corresponding environment variable. The naming convention is:

  • Start with the INSIGHTS_ prefix
  • Replace dots with underscores
  • Convert to uppercase
FlagEnvironment Variable
--log-levelINSIGHTS_LOG_LEVEL
--data-dirINSIGHTS_DATA_DIR
--serverINSIGHTS_NATS_SERVER
--sys.credsINSIGHTS_SYS_CREDS
--scraper.intervalINSIGHTS_SCRAPER_INTERVAL
--web.portINSIGHTS_WEB_PORT
--db.retention.durationINSIGHTS_DB_RETENTION_DURATION
--sink.retentionINSIGHTS_SINK_RETENTION
--simulatorINSIGHTS_SIMULATOR

Nested sections add their prefix. For example, a scraper NATS connection uses INSIGHTS_SCRAPER_NATS_SERVER.

Subsystem Toggles

Each subsystem is switched on or off with a shorthand named after it: --scraper, --indexer, --web, --simulator, --prometheus, --updater, --telemetry on the command line, and INSIGHTS_SCRAPER, INSIGHTS_WEB, INSIGHTS_UPDATER, … in the environment. YAML is the exception: a section is a map there, so it keeps using its own enabled: key.

./insights --simulator --web=false --updater=false
INSIGHTS_SIMULATOR=true INSIGHTS_WEB=false INSIGHTS_UPDATER=false ./insights
web:
  enabled: false
updater:
  enabled: false

The verbose forms are accepted too: --web.enabled=false (hidden from --help) and INSIGHTS_WEB_ENABLED=false. The shorthand is applied last, so it wins when both are set: INSIGHTS_WEB=false with INSIGHTS_WEB_ENABLED=true leaves the web server off. A command-line flag still beats both environment variables.

The tables below list the shorthand as the CLI and environment form for each toggle; the YAML key is unchanged.

Configuration Sections

log-level

Controls logging verbosity. Accepted values: debug, info, warn, error.

FlagEnvDefault
--log-levelINSIGHTS_LOG_LEVELinfo

license

License key for a trial build. Provide either a raw JWT string or a path to a file containing the JWT. If both are set, the file takes precedence.

A trial build requires a license unless the simulator is enabled (--simulator) or the node runs neither the indexer nor the scraper, such as insights web. Other builds require no license; leave this section unset there, since a license that is set is still verified at startup. See Trial for evaluation, Configure the License for configuring a trial license, and License Expiry for renewing one.

FlagEnvDefault
--license.tokenINSIGHTS_LICENSE_TOKEN(empty)
--license.fileINSIGHTS_LICENSE_FILE(empty)

data-dir

Base directory for persistent storage. This directory holds the DuckDB database file (insights.db, or one systems/<id>.db per system on a node with several systems) and the embedded server's JetStream data (nats/).

When unset, a temporary directory is created and all data is lost on restart. Set this for any deployment where you want data to survive restarts.

FlagEnvDefault
--data-dirINSIGHTS_DATA_DIR(temp dir)

node.*: Node Identity

Names this process. The node id addresses process diagnostics on the node-scoped API space ($INS.node.<id>.ops.pprof, $INS.node.<id>.ops.version, ...) and serves as a stable label for operator tooling, so it must survive restarts and deploys.

Defaults to the id of the system this node serves, which is operator-assigned and therefore survives a reschedule. A node serving several systems has no single id to borrow and must be named; a node serving none (a web node) falls back to the hostname, sanitized to a subject-safe token. Allowed characters: letters, digits, _, -.

Systems servedDefault
one (either config shape)that system's id
several (systems: list)none; node.id is required
none (web-only node)hostname (sanitized)
FlagEnvDefault
--node.idINSIGHTS_NODE_IDsee above

Two processes serving the same system must be named apart. Insights checks this at startup over $INS.ping and refuses to start on a clash rather than letting two nodes answer for one identity.

Labels. node.metadata is a map of operator-assigned labels describing where the process runs (region, rack, ...). They are reported on $INS.ping, so insights node list and the web UI can filter and group nodes by them; nothing addresses a subject with them. Keys allow letters, digits, _, - and . (up to 64 characters); values are free text without control characters (up to 256 characters); at most 16 pairs. An invalid label fails startup. node.metadata is YAML-only.

node:
  id: hub-1
  metadata:
    region: us-east-1
    rack: b12

system.*: System Identity

Names the monitored NATS system. The system id addresses everything that belongs to the system on the system-scoped API space ($INS.sys.<id>.db.query, $INS.sys.<id>.checks.list, ...). It is operator-assigned: no stable NATS system identifier can be derived (cluster names break on superclusters; system-account nkeys collapse for leaf nodes sharing a hub's system account). Allowed characters: letters, digits, _, -.

FlagEnvDefault
--system.idINSIGHTS_SYSTEM_IDdefault

Labels. system.metadata labels the monitored system (env, team, ...) on the same terms as node.metadata. Declare them where the system is scraped: a node that indexes a system without scraping it (a collector fills its stream) refuses to start with system.metadata set, because the collector describes the system. system.metadata is YAML-only.

The client subcommands read the same system.id / node.id keys from a shared config file to pick their target. Their own --system/--node flags and INSIGHTS_SYSTEM/INSIGHTS_NODE envs (distinct from the server's INSIGHTS_SYSTEM_ID/INSIGHTS_NODE_ID) override them. See CLI.

systems: Multiple Systems

One instance can own several monitored systems. Each gets its own DuckDB instance (<data-dir>/systems/<id>.db), its own JetStream stream, its own indexer, and its own $INS.sys.<id>.* API. Nothing is shared or steered between them. Set the systems: list only on a node monitoring more than one system; a single-system node (the usual deployment, an edge collector, a federated instance) keeps the flat system:/sys:/scraper:/sink: config and leaves systems: empty.

For a collector-fed system (a systems: entry with no scrape: block), the stream is filled by a NATS mirror of the stream an edge collector (insights-collector serve) writes, rather than by a local scraper.

The list is YAML-only (there are no --systems.* flags). It is mutually exclusive with the flat single-system config: setting systems: together with a non-default system.id, a sys.* connection, or leaving indexer.enabled off is a config error (a node with this list indexes every listed system). The simulator cannot run with systems:.

Each entry:

KeyDefaultDescription
id(required)System identifier ($INS.sys.<id>.*, stream naming). Subject-safe token; unique across the list.
scrape.nats.*(none)Connection to the monitored system. Present ⇒ this node scrapes it (outbound-scraper mode); absent ⇒ collector-fed (a mirror fills its stream and this node only indexes). Same fields as sys.*.
scrape.intervalscraper.intervalScrape cadence for this system.
scrape.timeoutscraper.timeoutScrape request timeout.
retentionsink.retentionStream buffer depth. The database keeps history; this bounds the ingest buffer only. Enforced by pruning whole epochs, not by the stream's max_age.
stream.namescrape_<id> / mirror_<id>JetStream stream name: mirror_<id> for a collector-fed entry, scrape_<id> for one this node scrapes. Override only to adopt a stream an operator already built. The subject prefix is never configured here: a scraper on this node publishes under $INS.sys.<id>.scrape, and a collector-fed mirror declares its origin namespace in mirror.filter_subject.
stream.replicassink.replicasStream replica count. Requires a clustered sink.
stream.storagesink.storageStream storage class, file or memory.
mirror-api-prefix(none)Route to a collector-fed origin's JetStream API when it is not reached by a JetStream domain, such as a subject mapping or account import under a prefix of your choosing. A domain needs nothing here: the collector reports its own over $INS.sys.<id>.ops.sink.info. Rejected on an entry with a scrape: block.
metadata(none)Labels for this system, on the same terms as system.metadata. Allowed only on an entry with a scrape: block; a collector-fed system is labeled by its collector.
db.memory-limittop-level db.memory-limitPer-instance DuckDB buffer-pool cap. Each system has its own pool, so this is a per-instance value, not a shared budget.
db.threadstop-level db.threadsPer-instance DuckDB worker threads.
check-thresholdstop-level check-thresholdsPer-system check overrides, merged per check code onto the top-level set.
disabled-checkstop-level disabled-checksCheck codes this system turns off, unioned with the top-level list. An entry can add codes; it cannot re-enable one the top level disabled.

Still node-wide (not per-entry): data-dir, node, nats (the API connection), sink.embed, web, log-level, license, updater, and db.retention (the database's epoch-retention sweep). The top-level db: section is the per-instance default that each entry overrides.

On a node serving several systems:

  • Webhook endpoints are node-wide but scopable per system. A node serving several systems delivers every system's alerts to every endpoint by default; each alert carries a system label and each delivery-log entry records which system it was for. Scope an endpoint to a subset with its systems: field (see notifications).

sys.*: System Account Connection

NATS connection used to scrape the target NATS system. Insights issues $SYS requests over this connection to collect server metrics. This is required when the simulator is disabled.

FlagEnvDescription
--sys.serverINSIGHTS_SYS_SERVERNATS server URL
--sys.credsINSIGHTS_SYS_CREDSPath to credentials file (.creds)
--sys.contextINSIGHTS_SYS_CONTEXTNATS context name (from nats context)
--sys.userINSIGHTS_SYS_USERUsername for basic auth
--sys.passwordINSIGHTS_SYS_PASSWORDPassword for basic auth
--sys.nkeyINSIGHTS_SYS_NKEYNKey seed for authentication
--sys.jwtINSIGHTS_SYS_JWTUser JWT for authentication
--sys.tls-certINSIGHTS_SYS_TLS_CERTTLS certificate path
--sys.tls-keyINSIGHTS_SYS_TLS_KEYTLS key path
--sys.tls-ca-certINSIGHTS_SYS_TLS_CA_CERTTLS CA certificate path
--sys.tls-firstINSIGHTS_SYS_TLS_FIRSTPerform TLS handshake before NATS protocol
--sys.socks-proxyINSIGHTS_SYS_SOCKS_PROXYSOCKS proxy URL
--sys.inbox-prefixINSIGHTS_SYS_INBOX_PREFIXRequest/reply inbox prefix (default _INBOX)

Inbox prefix. Leave inbox-prefix empty unless the account is not granted _INBOX.>, a common least-privilege setup on Synadia Cloud. Every reply Insights receives lands under this prefix, so the account must allow subscribing to <prefix>.>.

System account permissions. When using a dedicated user JWT instead of the full system account credentials, see the deployment guide for the required granular subject permissions.

nats.*: Top-Level NATS Connection

NATS connection used by the API server and as the default for the indexer and scraper if they do not specify their own connections.

This connection is only needed when using an external NATS sink (--sink.embed=false). When the embedded sink is enabled (the default), Insights manages its own internal NATS server automatically.

The flags mirror sys.* above. Drop the sys. prefix to get the nats-CLI-style client flags (e.g., --server, --creds, --context), with matching environment variables (--server reads INSIGHTS_NATS_SERVER) and YAML under nats:. The --nats.* spellings (--nats.server, ...) are accepted as hidden aliases.

Connection fallback order: scraper.nats falls back to indexer.nats, which falls back to nats (top-level).

db.*: Database

DuckDB configuration options.

FlagEnvDefaultDescription
--db.memory-limitINSIGHTS_DB_MEMORY_LIMIT4GiBDuckDB memory limit. Caps the buffer pool to prevent swapping
--db.threadsINSIGHTS_DB_THREADS0DuckDB worker threads (0 = auto, uses all cores)
--db.retention.durationINSIGHTS_DB_RETENTION_DURATION768hHow long to keep data in DuckDB (0 = disabled)
--db.retention.intervalINSIGHTS_DB_RETENTION_INTERVAL10mMinimum time between retention sweeps; a sweep runs right after the first epoch commit past it
--db.memory-profile.enabledINSIGHTS_DB_MEMORY_PROFILE_ENABLEDtrueEnable the live DuckDB memory profiler (samples duckdb_memory() for ops sizing / ops memory)
--db.memory-profile.intervalINSIGHTS_DB_MEMORY_PROFILE_INTERVAL2sMemory profiler sampling interval
--db.memory-profile.windowINSIGHTS_DB_MEMORY_PROFILE_WINDOW15mMemory profiler rolling window (peak + chart history)
--db.query-timeoutINSIGHTS_DB_QUERY_TIMEOUT2mMax duration for a single $INS.db.query statement (0 = unlimited)
--db.query-max-rowsINSIGHTS_DB_QUERY_MAX_ROWS100000Max rows the non-streaming $INS.db.query may return; a larger result is rejected with a 413 pointing at the streaming endpoint (0 = unlimited)
--db.query-stream.windowINSIGHTS_DB_QUERY_STREAM_WINDOW16Max unacknowledged stream chunks in flight (credit window)
--db.query-stream.chunk-sizeINSIGHTS_DB_QUERY_STREAM_CHUNK_SIZE512KiBTarget size of each streamed Arrow chunk
--db.query-stream.batch-timeoutINSIGHTS_DB_QUERY_STREAM_BATCH_TIMEOUT30sMax time to produce each stream batch (0 = unlimited)
--db.query-stream.ack-idle-timeoutINSIGHTS_DB_QUERY_STREAM_ACK_IDLE_TIMEOUT30sAbort a stream if the client stops acknowledging (0 = unlimited)
--db.query-stream.compressionINSIGHTS_DB_QUERY_STREAM_COMPRESSIONnoneStream chunk compression: none, lz4, or zstd (uses additional CPU)
--db.query-stream.max-rowsINSIGHTS_DB_QUERY_STREAM_MAX_ROWS1000000Abort a streamed query after this many rows, a safety limit for runaway unscoped scans (0 = unlimited)

The $INS.db.query.stream endpoint streams results as windowed Apache Arrow chunks so neither side buffers the whole result; insights db query uses it automatically. --db.query-max-rows caps only the non-streaming $INS.db.query endpoint. See API Reference → Query Endpoints for the wire protocol.

scraper.*: Scraper

Controls how Insights collects metrics from NATS servers.

FlagEnvDefaultDescription
--scraperINSIGHTS_SCRAPERtrueEnable or disable the scraper
--scraper.intervalINSIGHTS_SCRAPER_INTERVAL1mTime between scrape cycles
--scraper.timeoutINSIGHTS_SCRAPER_TIMEOUT30sTimeout for individual scrape requests
--scraper.filter.allow.serversINSIGHTS_SCRAPER_FILTER_ALLOW_SERVERS(empty)Scrape only servers with these exact names
--scraper.filter.allow.clustersINSIGHTS_SCRAPER_FILTER_ALLOW_CLUSTERS(empty)Scrape only servers in these exact clusters
--scraper.filter.allow.tagsINSIGHTS_SCRAPER_FILTER_ALLOW_TAGS(empty)Scrape only servers carrying these exact tags
--scraper.filter.deny.serversINSIGHTS_SCRAPER_FILTER_DENY_SERVERS(empty)Never scrape servers with these exact names
--scraper.filter.deny.clustersINSIGHTS_SCRAPER_FILTER_DENY_CLUSTERS(empty)Never scrape servers in these exact clusters
--scraper.filter.deny.tagsINSIGHTS_SCRAPER_FILTER_DENY_TAGS(empty)Never scrape servers carrying these exact tags

The scraper optionally accepts its own NATS connection via --scraper.nats.* flags, falling back to the indexer NATS and then the top-level NATS connection.

Server filter. By default every discovered server is scraped. The --scraper.filter.* lists restrict the scrape set by exact match on server name, cluster name, or tag. Deny takes precedence over allow, and when any allow list is set a server must match it to be scraped. Excluded servers receive no monitoring requests at all. Only the unavoidable discovery PING and the account-scoped ACCSTATZ broadcast reach them, and their replies to those are dropped before storage.

indexer.*: Indexer

Controls how scraped data is processed and stored in DuckDB.

FlagEnvDefaultDescription
--indexerINSIGHTS_INDEXERtrueEnable or disable the indexer
--indexer.stream-latestINSIGHTS_INDEXER_STREAM_LATESTfalseStart consuming from the latest message
--indexer.stream-epochINSIGHTS_INDEXER_STREAM_EPOCH0Start consuming from a specific epoch number
--indexer.stream-filtersINSIGHTS_INDEXER_STREAM_FILTERS(empty)Comma-separated list of endpoints to process (e.g., varz,jsz,connz)
--indexer.stream-intervalINSIGHTS_INDEXER_STREAM_INTERVAL0sDownsample interval: skip epochs closer together than this

web.*: Web Server

Controls the built-in web UI and HTTP server.

FlagEnvDefaultDescription
--webINSIGHTS_WEBtrueEnable or disable the web server
--web.hostnameINSIGHTS_WEB_HOSTNAME127.0.0.1Bind hostname (0.0.0.0 for all interfaces)
--web.portINSIGHTS_WEB_PORT8080Bind port
--web.session-seedINSIGHTS_WEB_SESSION_SEEDinsightsSeed for secure session cookies
--web.tlsINSIGHTS_WEB_TLSfalseEnable TLS (HTTPS). HTTP/2 is automatically available via ALPN
--web.tls-certINSIGHTS_WEB_TLS_CERT(empty)Path to TLS certificate (PEM). Required when --web.tls is set
--web.tls-keyINSIGHTS_WEB_TLS_KEY(empty)Path to TLS private key (PEM). Required when --web.tls is set
--web.tls-ca-certINSIGHTS_WEB_TLS_CA_CERT(empty)Path to TLS CA certificate for verifying client certificates
--web.external-urlINSIGHTS_WEB_EXTERNAL_URL(empty)Public base URL of this instance (e.g. https://insights.example.com); used to build links in notification alert payloads

TLS behavior: TLS is disabled by default. When enabled (--web.tls), you must supply your own certificate and key (--web.tls-cert / --web.tls-key); enabling TLS without them fails at startup. Insights does not generate a self-signed certificate.

Session seed: The default value "insights" preserves sessions across restarts but should be changed to a unique secret for production deployments.

sink.*: Embedded Sink

Controls the embedded NATS server used for storing scraped data as a JetStream stream.

FlagEnvDefaultDescription
--sink.embedINSIGHTS_SINK_EMBEDtrueUse the embedded NATS server
--sink.config-fileINSIGHTS_SINK_CONFIG_FILE(empty)NATS server config file for the embedded server. The file must exist; it is parsed first and Insights applies its own settings on top
--sink.hostINSIGHTS_SINK_HOST127.0.0.1Bind host for the embedded server
--sink.portINSIGHTS_SINK_PORT0Bind port (0 = random)
--sink.streamINSIGHTS_SINK_STREAMscrapeJetStream stream name. The collector derives scrape_<system.id> from the system id when this is left at the default, so a central node mirroring the collector lands on the same name
--sink.batch-sizeINSIGHTS_SINK_BATCH_SIZE500Batch size for sink operations
--sink.retentionINSIGHTS_SINK_RETENTION24hHow long to keep scraped data in the sink stream (0 = unlimited). Enforced by pruning whole epochs, not by the stream's max_age; a message-level limit would leave the indexer a scrape truncated mid-epoch
--sink.replicasINSIGHTS_SINK_REPLICAS1Stream replica count. Requires a clustered sink; rejected with --sink.embed
--sink.storageINSIGHTS_SINK_STORAGEfileStream storage class: file or memory

Set --sink.embed=false to use an external NATS cluster with JetStream instead of the embedded server. See the deployment guide for external sink topologies.

simulator.*: Simulator

The built-in simulator starts real in-process NATS clusters with traffic workloads, allowing you to explore Insights with zero external dependencies.

FlagEnvDefaultDescription
--simulatorINSIGHTS_SIMULATORfalseEnable the embedded simulator
--simulator.profileINSIGHTS_SIMULATOR_PROFILEjs-smallSimulator profile

Available profiles control the size and topology of the simulated deployment:

Profile FamilyVariantsDescription
core-small, medium, largeCore NATS servers
js-small, medium, largeNATS with JetStream
super-small, medium, largeSuper-cluster topology
leaf-small, medium, largeLeaf node topology
super-leaf-small, medium, largeSuper-cluster with leaf nodes

prometheus.*: Prometheus Metrics

Controls the Prometheus-compatible /metrics endpoint.

FlagEnvDefaultDescription
--prometheusINSIGHTS_PROMETHEUStrueEnable the metrics endpoint
--prometheus.hostnameINSIGHTS_PROMETHEUS_HOSTNAME127.0.0.1Bind hostname
--prometheus.portINSIGHTS_PROMETHEUS_PORT9091Bind port
--prometheus.aggregateINSIGHTS_PROMETHEUS_AGGREGATEfalseServe every node's metrics from this endpoint, not just this node's
--prometheus.timeoutINSIGHTS_PROMETHEUS_TIMEOUT2sBudget for one aggregated collection. Ignored unless aggregating

By default /metrics serves only the metrics of the node serving it. aggregate makes that one endpoint answer for the whole deployment: each scrape discovers the nodes over $INS.ping and asks each one for its snapshot. Enable it on exactly one node. Scraping two aggregators reports every series twice, once per endpoint, and a sum() over them double-counts. insights prometheus serves the same thing as a standalone process for when the scrape target should not be a full node. The series and labels are listed in Metrics.

updater.*: Version Checker

Periodically checks GitHub for a newer release and notifies via a log message and a badge in the web UI. Does not download or replace the binary. The release repository is compiled into the binary, so there is no URL or channel to configure.

FlagEnvDefaultDescription
--updaterINSIGHTS_UPDATERtrueEnable version checking
--updater.intervalINSIGHTS_UPDATER_INTERVAL1hInterval between update checks

telemetry.*: Product Telemetry

Trial builds send a small usage pulse on this interval, the first at startup. Other builds contain no reporter, and these settings parse but do nothing there. There is no destination setting: where a pulse goes is fixed when the binary is built. A pulse carries a random instance id, the release version and platform, the scrape and pulse intervals, the size of the watched environment, and usage counts from the web UI and the CLI, MCP and HTTP clients. It carries nothing about the monitored system itself: no server, cluster, account, subject, stream or consumer names, no addresses, no message data, no configuration values and no query text. Telemetry lists every field.

FlagEnvDefaultDescription
--telemetryINSIGHTS_TELEMETRYtrueSend product telemetry
--telemetry.intervalINSIGHTS_TELEMETRY_INTERVAL5mInterval between pulses. Must be positive while telemetry is on
--telemetry.printINSIGHTS_TELEMETRY_PRINTfalseLog every pulse, so you can read exactly what leaves the process

insights web takes only the on/off switch: it sends no pulse of its own, and switching it off stops it passing UI usage to the nodes that report it.

check-thresholds

Per-check threshold overrides. Many checks accept one or more tunable parameters (e.g. a CPU percentage, a lag interval, a byte size) that control when the check produces a finding. Defaults suit most deployments, but production environments often need different thresholds.

Overrides are keyed by check code and parameter name. The parameter names and default values for each check are listed in the Checks Reference. Any value shown as a backtick-quoted identifier in the Threshold column (e.g. `cpu_percent`) is tunable here.

Configure overrides in your YAML config file:

check-thresholds:
  server-003:
    cpu_percent: 80 # flag servers above 80% CPU (default: 90)
  stream-002:
    lag_percent: 20 # flag replica lag above 20% (default: 10)
  stream-022:
    max_memory: 500 MiB # memory-backed streams > 500 MiB

Duration parameters accept Go duration strings (e.g. 50ms, 5m, 24h). A parameter that bounds a window measured across scrapes (a persistence or lookback window such as system-009's sustain or system-004's window) must be greater than or equal to the scrape interval, since a shorter window can never span two scrapes; insights serve fails to start with a validation error otherwise on a node that scrapes the system. insights config check does not apply this floor. A duration compared against a value sampled within one scrape, such as an RTT threshold, carries no such floor.

Size parameters accept IEC binary strings (e.g. 64 KiB, 1 MiB, 10 GiB; powers of 1024). A bare number is an exact byte count, so 1 MiB and 1048576 configure the same threshold. Write sizes in IEC units (MiB, GiB), not SI suffixes (MB, GB).

Optimization checks also accept a special lookback parameter that controls the analysis window for range-based checks:

check-thresholds:
  account-011:
    lookback: 4h

Unknown parameter names and check codes fail startup with an error naming the entry, and insights config check reports the same errors without starting the node. A code written in the uppercase, underscored form (SERVER_003) is reported with its current spelling (server-003); a code that matches no check in either spelling is reported as unknown, so find its replacement with insights checks list. An unknown parameter is reported with the parameter names the check accepts, or with its replacement when it is a renamed one. lookback is accepted only on optimization checks. A retired check code (server-049) is accepted with a warning and its values are ignored.

Threshold overrides are a YAML-only setting; there is no equivalent command-line flag or environment variable. Use --config to load a YAML file that contains your overrides.

disabled-checks

A list of check codes this instance turns off. Use it for a check that cannot be acted on in your topology: one that is structurally true of your deployment rather than a symptom of anything, where no threshold value would make it meaningful.

disabled-checks:
  - account-012

A disabled check keeps running and keeps its history. It is shown everywhere it would otherwise appear (the findings grids, the check catalog, entity pages, the health timeline, insights checks list, insights checks info and insights checks findings), marked disabled, with its real findings. The checks.list, checks.info and checks.findings endpoints, and the MCP tools over them, carry the same fact as disabled: true. What changes is that it is not graded and not delivered:

  • The category and overall health percentages leave it out on both sides. Its findings do not count as firing and its entities do not count as applicable, so a check you have decided not to act on cannot move the score either way. The health timeline's stat cards (current, new, resolved, flapping) leave it out the same way.
  • Nothing it finds becomes a notification. Its findings never enter the findings tracker, so no advisory is published and no webhook or alert is delivered, and nothing is re-sent on the standing-alert cadence. Turning it off does not send a resolve for anything it had firing: the condition is still true, only the delivery stopped. The Notifications page marks a subscription to a disabled check so the silence is not read as health.

Unknown check codes fail startup with an error naming the entry. A code in the uppercase, underscored form (ACCOUNT_012) is reported with its current spelling; any other unknown code is reported as unknown. A retired code is accepted with a warning and has no effect. insights config check runs the same validation without starting the node.

On a node with several systems, a systems: entry's list is unioned with the top-level list: an entry adds codes for its own system and can never re-enable one disabled at the top level.

disabled-checks is a YAML-only setting; there is no equivalent command-line flag or environment variable.

notifications

Outbound notification endpoints. When a check changes state (fires or resolves), Insights delivers the transition to any endpoint subscribed to that check code. Endpoints are declared under two keys by delivery format:

  • webhook: receives the full Alertmanager-compatible payload envelope.
  • alertmanager: receives a bare alert array compatible with the Alertmanager v2 POST /api/v2/alerts API.

Both endpoint types take the same per-endpoint fields:

FieldDefaultDescription
name(required)Human-readable name; must be unique across all endpoints
url(required)Destination URL; must be http or https
enabledtrueWhether the endpoint is active
auth-type(none)Authentication scheme: basic, bearer, or hmac
auth-user(empty)Username for basic auth
auth-token(empty)Password (basic), token (bearer), or secret (hmac, sent as X-Hub-Signature-256)
subscriptions(empty)Check-code patterns this endpoint receives (e.g. [server-*, stream-002])
ignore(empty)Check-code patterns dropped after a subscription match
systems(empty)Systems this endpoint delivers for; must be systems this node owns. Empty delivers for every system on the node

A pattern is an exact code (server-001), a prefix with a trailing wildcard (server-*), or * for every code. ignore is applied after subscriptions, so it carves exceptions out of a wildcard. A pattern that matches no check code fails startup; an uppercase, underscored pattern (SERVER_*) is reported with its current spelling.

Note systems is the inverse of subscriptions: an empty subscriptions list delivers nothing (subscribing to a check code is explicit), but an empty systems list delivers for every system the node owns (the sensible default on a node serving one or a few operator-named systems). On a node serving several systems, scope an endpoint to a subset by naming them.

notifications:
  webhook:
    - name: 'PagerDuty Relay'
      url: 'https://example.com/webhook'
      enabled: true
      auth-type: 'bearer'
      auth-token: '…'
      subscriptions: [server-*, stream-002]
      ignore: [server-046]
  alertmanager:
    - name: 'local-am'
      url: 'http://localhost:9093/api/v2/alerts'
      subscriptions: [server-001]

Notifications are a YAML-only setting; there are no equivalent flags or environment variables. Delivery timing is fixed: a 10s request timeout and up to 3 attempts with exponential backoff, or a single attempt when the receiver answers with a 4xx other than 429. A delivery that still fails is retried for that endpoint on a backoff capped at once a minute until it succeeds. Every endpoint is validated at startup: a missing name or URL, a malformed or non-http(s) URL, a duplicate name, an unknown auth-type, a pattern matching no check code, or a systems entry naming a system this node does not own fails startup with a clear error rather than being silently dropped. Alert payload links use --web.external-url when set. The web UI's Notifications page shows the configured endpoints and their delivery logs and can send a synthetic test delivery, but endpoints themselves are managed only through the config file. See the Notifications guide for the full workflow.