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:
- CLI flags (e.g.,
--server nats://host:4222) - Environment variables (e.g.,
INSIGHTS_NATS_SERVER=nats://host:4222) - YAML config file (via
--config,INSIGHTS_CONFIG, or a default search path; see Config File) - 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):
<user-config-dir>/insights/config.yaml, e.g.~/.config/insights/config.yamlon Linux,~/Library/Application Support/insights/config.yamlon macOS../insights.yaml, auto-discovered in the working directory.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).
Note:
./insights.yamlis read from the current working directory, so any directory you runinsightsfrom can supply configuration (as withgit,cargo, and similar tools). Avoid runninginsightsfrom untrusted or world-writable directories, or pass--configexplicitly. CLI flags andINSIGHTS_*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.
For a complete annotated example, see config.example.yaml.
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
| Flag | Environment Variable |
|---|---|
--log-level | INSIGHTS_LOG_LEVEL |
--data-dir | INSIGHTS_DATA_DIR |
--server | INSIGHTS_NATS_SERVER |
--sys.creds | INSIGHTS_SYS_CREDS |
--scraper.interval | INSIGHTS_SCRAPER_INTERVAL |
--web.port | INSIGHTS_WEB_PORT |
--db.retention.duration | INSIGHTS_DB_RETENTION_DURATION |
--sink.retention | INSIGHTS_SINK_RETENTION |
--simulator | INSIGHTS_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, 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.
| Flag | Env | Default |
|---|---|---|
--log-level | INSIGHTS_LOG_LEVEL | info |
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. For trials and expiry, see Licensing & Trial.
| Flag | Env | Default |
|---|---|---|
--license.token | INSIGHTS_LICENSE_TOKEN | (empty) |
--license.file | INSIGHTS_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.
| Flag | Env | Default |
|---|---|---|
--data-dir | INSIGHTS_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 served | Default |
|---|---|
| one (either config shape) | that system's id |
several (systems: list) | none; node.id is required |
| none (web-only node) | hostname (sanitized) |
| Flag | Env | Default |
|---|---|---|
--node.id | INSIGHTS_NODE_ID | see 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: central
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, _, -.
| Flag | Env | Default |
|---|---|---|
--system.id | INSIGHTS_SYSTEM_ID | default |
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 → Selecting a system or node.
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, a collector, a federated site node) 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 rather than a local scraper. See Federated Deployment for the collector, the leafnode setup, and the central node's mirror.
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 a systems: list always indexes every listed system). The simulator cannot run with systems:.
Each entry:
| Key | Default | Description |
|---|---|---|
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.interval | scraper.interval | Scrape cadence for this system. |
scrape.timeout | scraper.timeout | Scrape request timeout. |
retention | sink.retention | Stream 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.name | scrape_<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.replicas | sink.replicas | Stream replica count. Requires a clustered sink. |
stream.storage | sink.storage | Stream 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-limit | top-level db.memory-limit | Per-instance DuckDB buffer-pool cap. Each system has its own pool, so this is a per-instance value, not a shared budget. |
db.threads | top-level db.threads | Per-instance DuckDB worker threads. |
check-thresholds | top-level check-thresholds | Per-system check overrides, merged per check code onto the top-level set. |
disabled-checks | top-level disabled-checks | Check 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
systemlabel and each delivery-log entry records which system it was for. Scope an endpoint to a subset with itssystems:field (seenotifications). - The
opsPostgreSQL attach (INSIGHTS_DB_ATTACH) is single-system only: it is applied only in the flat config, never with asystems:list.
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.
| Flag | Env | Description |
|---|---|---|
--sys.server | INSIGHTS_SYS_SERVER | NATS server URL |
--sys.creds | INSIGHTS_SYS_CREDS | Path to credentials file (.creds) |
--sys.context | INSIGHTS_SYS_CONTEXT | NATS context name (from nats context) |
--sys.user | INSIGHTS_SYS_USER | Username for basic auth |
--sys.password | INSIGHTS_SYS_PASSWORD | Password for basic auth |
--sys.nkey | INSIGHTS_SYS_NKEY | NKey seed for authentication |
--sys.jwt | INSIGHTS_SYS_JWT | User JWT for authentication |
--sys.tls-cert | INSIGHTS_SYS_TLS_CERT | TLS certificate path |
--sys.tls-key | INSIGHTS_SYS_TLS_KEY | TLS key path |
--sys.tls-ca-cert | INSIGHTS_SYS_TLS_CA_CERT | TLS CA certificate path |
--sys.tls-first | INSIGHTS_SYS_TLS_FIRST | Perform TLS handshake before NATS protocol |
--sys.socks-proxy | INSIGHTS_SYS_SOCKS_PROXY | SOCKS proxy URL |
--sys.inbox-prefix | INSIGHTS_SYS_INBOX_PREFIX | Request/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: the indexer uses indexer.nats, or the top-level nats if that is unset. The scraper uses scraper.nats, then the indexer's connection, then the top-level nats.
db.*: Database
DuckDB configuration options.
| Flag | Env | Default | Description |
|---|---|---|---|
--db.memory-limit | INSIGHTS_DB_MEMORY_LIMIT | 4GiB | DuckDB memory limit. Caps the buffer pool to prevent swapping |
--db.threads | INSIGHTS_DB_THREADS | 0 | DuckDB worker threads (0 = auto, uses all cores) |
--db.retention.duration | INSIGHTS_DB_RETENTION_DURATION | 768h | How long to keep data in DuckDB (0 = disabled) |
--db.retention.interval | INSIGHTS_DB_RETENTION_INTERVAL | 10m | Minimum time between retention sweeps; a sweep runs right after the first epoch commit past it |
--db.memory-profile.enabled | INSIGHTS_DB_MEMORY_PROFILE_ENABLED | true | Enable the live DuckDB memory profiler (samples duckdb_memory() for ops sizing / ops memory) |
--db.memory-profile.interval | INSIGHTS_DB_MEMORY_PROFILE_INTERVAL | 2s | Memory profiler sampling interval |
--db.memory-profile.window | INSIGHTS_DB_MEMORY_PROFILE_WINDOW | 15m | Memory profiler rolling window (peak + chart history) |
--db.query-timeout | INSIGHTS_DB_QUERY_TIMEOUT | 2m | Max duration for a single $INS.db.query statement (0 = unlimited) |
--db.query-max-rows | INSIGHTS_DB_QUERY_MAX_ROWS | 100000 | Max 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.window | INSIGHTS_DB_QUERY_STREAM_WINDOW | 16 | Max unacknowledged stream chunks in flight (credit window) |
--db.query-stream.chunk-size | INSIGHTS_DB_QUERY_STREAM_CHUNK_SIZE | 512KiB | Target size of each streamed Arrow chunk |
--db.query-stream.batch-timeout | INSIGHTS_DB_QUERY_STREAM_BATCH_TIMEOUT | 30s | Max time to produce each stream batch (0 = unlimited) |
--db.query-stream.ack-idle-timeout | INSIGHTS_DB_QUERY_STREAM_ACK_IDLE_TIMEOUT | 30s | Abort a stream if the client stops acknowledging (0 = unlimited) |
--db.query-stream.compression | INSIGHTS_DB_QUERY_STREAM_COMPRESSION | none | Stream chunk compression: none, lz4, or zstd (uses additional CPU) |
--db.query-stream.max-rows | INSIGHTS_DB_QUERY_STREAM_MAX_ROWS | 1000000 | Abort 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.
| Flag | Env | Default | Description |
|---|---|---|---|
--scraper | INSIGHTS_SCRAPER | true | Enable or disable the scraper |
--scraper.interval | INSIGHTS_SCRAPER_INTERVAL | 1m | Time between scrape cycles |
--scraper.timeout | INSIGHTS_SCRAPER_TIMEOUT | 30s | Timeout for individual scrape requests |
--scraper.filter.allow.servers | INSIGHTS_SCRAPER_FILTER_ALLOW_SERVERS | (empty) | Scrape only servers with these exact names |
--scraper.filter.allow.clusters | INSIGHTS_SCRAPER_FILTER_ALLOW_CLUSTERS | (empty) | Scrape only servers in these exact clusters |
--scraper.filter.allow.tags | INSIGHTS_SCRAPER_FILTER_ALLOW_TAGS | (empty) | Scrape only servers carrying these exact tags |
--scraper.filter.deny.servers | INSIGHTS_SCRAPER_FILTER_DENY_SERVERS | (empty) | Never scrape servers with these exact names |
--scraper.filter.deny.clusters | INSIGHTS_SCRAPER_FILTER_DENY_CLUSTERS | (empty) | Never scrape servers in these exact clusters |
--scraper.filter.deny.tags | INSIGHTS_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.
| Flag | Env | Default | Description |
|---|---|---|---|
--indexer | INSIGHTS_INDEXER | true | Enable or disable the indexer |
--indexer.stream-latest | INSIGHTS_INDEXER_STREAM_LATEST | false | Start consuming from the latest message |
--indexer.stream-epoch | INSIGHTS_INDEXER_STREAM_EPOCH | 0 | Start consuming from a specific epoch number |
--indexer.stream-filters | INSIGHTS_INDEXER_STREAM_FILTERS | (empty) | Comma-separated list of endpoints to process (e.g., varz,jsz,connz) |
--indexer.stream-interval | INSIGHTS_INDEXER_STREAM_INTERVAL | 0s | Downsample interval: skip epochs closer together than this |
web.*: Web Server
Controls the built-in web UI and HTTP server.
| Flag | Env | Default | Description |
|---|---|---|---|
--web | INSIGHTS_WEB | true | Enable or disable the web server |
--web.hostname | INSIGHTS_WEB_HOSTNAME | 127.0.0.1 | Bind hostname (0.0.0.0 for all interfaces) |
--web.port | INSIGHTS_WEB_PORT | 8080 | Bind port |
--web.session-seed | INSIGHTS_WEB_SESSION_SEED | insights | Seed for secure session cookies |
--web.tls | INSIGHTS_WEB_TLS | false | Enable TLS (HTTPS). HTTP/2 is automatically available via ALPN |
--web.tls-cert | INSIGHTS_WEB_TLS_CERT | (empty) | Path to TLS certificate (PEM). Required when --web.tls is set |
--web.tls-key | INSIGHTS_WEB_TLS_KEY | (empty) | Path to TLS private key (PEM). Required when --web.tls is set |
--web.tls-ca-cert | INSIGHTS_WEB_TLS_CA_CERT | (empty) | Path to TLS CA certificate for verifying client certificates |
--web.external-url | INSIGHTS_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.
| Flag | Env | Default | Description |
|---|---|---|---|
--sink.embed | INSIGHTS_SINK_EMBED | true | Use the embedded NATS server |
--sink.config-file | INSIGHTS_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.host | INSIGHTS_SINK_HOST | 127.0.0.1 | Bind host for the embedded server |
--sink.port | INSIGHTS_SINK_PORT | 0 | Bind port (0 = random) |
--sink.stream | INSIGHTS_SINK_STREAM | scrape | JetStream stream name. insights-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-size | INSIGHTS_SINK_BATCH_SIZE | 500 | Batch size for sink operations |
--sink.retention | INSIGHTS_SINK_RETENTION | 24h | How long to keep scraped data in the sink stream (0 = unlimited). Enforced by pruning whole epochs, not by the stream's max_age, since a message-level limit would leave the indexer a scrape truncated mid-epoch |
--sink.replicas | INSIGHTS_SINK_REPLICAS | 1 | Stream replica count. Requires a clustered sink; rejected with --sink.embed |
--sink.storage | INSIGHTS_SINK_STORAGE | file | Stream 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.
| Flag | Env | Default | Description |
|---|---|---|---|
--simulator | INSIGHTS_SIMULATOR | false | Enable the embedded simulator |
--simulator.profile | INSIGHTS_SIMULATOR_PROFILE | js-small | Simulator profile |
Available profiles control the size and topology of the simulated deployment:
| Profile Family | Variants | Description |
|---|---|---|
core- | small, medium, large | Core NATS servers |
js- | small, medium, large | NATS with JetStream |
super- | small, medium, large | Super-cluster topology |
leaf- | small, medium, large | Leaf node topology |
super-leaf- | small, medium, large | Super-cluster with leaf nodes |
prometheus.*: Prometheus Metrics
Controls the Prometheus-compatible /metrics endpoint. See the Metrics reference for the full list of exported metrics.
| Flag | Env | Default | Description |
|---|---|---|---|
--prometheus | INSIGHTS_PROMETHEUS | true | Enable the metrics endpoint |
--prometheus.hostname | INSIGHTS_PROMETHEUS_HOSTNAME | 127.0.0.1 | Bind hostname |
--prometheus.port | INSIGHTS_PROMETHEUS_PORT | 9091 | Bind port |
--prometheus.aggregate | INSIGHTS_PROMETHEUS_AGGREGATE | false | Serve every node's metrics from this endpoint, not just this node's |
--prometheus.timeout | INSIGHTS_PROMETHEUS_TIMEOUT | 2s | Budget 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.
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. See Version Updates.
| Flag | Env | Default | Description |
|---|---|---|---|
--updater | INSIGHTS_UPDATER | true | Enable version checking |
--updater.interval | INSIGHTS_UPDATER_INTERVAL | 1h | Interval 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. See Telemetry for every field a pulse carries.
| Flag | Env | Default | Description |
|---|---|---|---|
--telemetry | INSIGHTS_TELEMETRY | true | Send product telemetry |
--telemetry.interval | INSIGHTS_TELEMETRY_INTERVAL | 5m | Interval between pulses. Must be positive while telemetry is on |
--telemetry.print | INSIGHTS_TELEMETRY_PRINT | false | Log 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 v2POST /api/v2/alertsAPI.
Both endpoint types take the same per-endpoint fields:
| Field | Default | Description |
|---|---|---|
name | (required) | Human-readable name; must be unique across all endpoints |
url | (required) | Destination URL; must be http or https |
enabled | true | Whether 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.