Synadia Insights

Search

The search API takes an input string and tries to parse it into a structured form with the semantics defined below. If that fails, it falls back to free-text fuzzy search.

Term Structure

A search term can have up to four components:

[[<entity>@]<attribute>:[<operator>]]<value>
  • value. The only required component. Without a qualifier, the value is treated as a free-text search against a predefined set of string attributes across all applicable entities. Quote a value to allow whitespace. Escape quotes with \".
  • attribute. Qualifies the value against a specific attribute. An attribute can span multiple entities (for example, name matches server, stream, consumer, and so on). Every attribute has a type, and the value is parsed accordingly.
  • operator. An explicit comparison operator for the attribute. Each type has its own set of allowed operators. All operators take a single value except .. (between), which takes two, and the implicit is set operator, which takes none.
  • entity. Fully qualifies the term by binding the attribute to a specific entity type.

Examples

nats-1                           # free-text: matches name, id, cluster, ip, etc.
name:nats-1                      # attribute: name equals "nats-1" (ILIKE) across all entities with name
server@name:nats-1               # entity + attribute: only match servers
rtt:>100ms                       # duration comparison: rtt greater than 100ms
rtt:20ms..40ms                   # range: rtt between 20ms and 40ms (inclusive)
in_bytes:>1gib                   # byte comparison: more than 1 GiB received
name:"With Spaces"               # quoted value with spaces
cpu:>80.5                        # float comparison
is_mirror:true                   # boolean match
description:                     # is set: the attribute holds a value, whatever it is
metadata.env:prod                # label: the entity is labeled env=prod
metadata.env:                    # label: the entity carries an env label at all
NOT slow_consumers:>0            # negation
(name:foo OR name:bar) rtt:<10ms # grouping with implicit AND

Multiple Terms

  • Terms are combined with logical operators: AND, OR, and NOT.
  • Without an explicit operator, adjacent terms are implicitly ANDed.
  • Grouping with parentheses () overrides default precedence.
  • Precedence (lowest to highest): OR < AND < NOT.
  • AND, OR, and NOT are keywords in either case: and and AND both apply. Quote a value that would otherwise read as a keyword.

Value Types

Every attribute has one of the following types. The value in a search term must be parseable as its attribute's type.

string

Plain text. String equality uses case-insensitive matching (ILIKE). Supports =, !=, and ~ (like) operators.

int

Integer number. Supports =, !=, >, >=, <, <=, and .. (between).

float

Floating-point number. Supports the same operators as int.

bool

Boolean value: true or false. Supports = and !=.

duration

A number with a time unit suffix. Stored internally as nanoseconds. Supports the same operators as int.

UnitSuffix
Nanosecondns
Microsecondus, µs
Millisecondms
Seconds
Minutem
Hourh
Dayd

bytes

A number with a byte size unit suffix (IEC binary units, powers of 1024). Supports the same operators as int.

UnitSuffix
Byteb
Kibibytekib
Mebibytemib
Gibibytegib
Tebibytetib

SI suffixes (kb, mb, gb, tb) are not accepted. Use the IEC equivalents above.

timestamp

An ISO-8601 date or datetime value. Supports the same operators as int (for ordering and range comparisons).

Examples: 2024-01-15, 2024-01-15T10:30:00Z

string[]

An array of strings. Matched using the same operators as string. The comparison checks if any element in the array matches.

Example: tags:nats-server matches any entity whose tags array contains an element matching nats-server.

Operators

Not all operators apply to all types. The table below shows which operators are valid for each type.

OperatorSyntaxstringstring[]intfloatdurationbytestimestampbool
Equal(implicit)YYYYYYYY
Not equal!=YYYYYYYY
Greater than>YYYYY
Greater or equal>=YYYYY
Less than<YYYYY
Less or equal<=YYYYY
Between..YYYYY
Like~YY
Is set(no value)YYYYYYYY

String equality (=) is case-insensitive (ILIKE). The ~ operator performs an ILIKE substring match.

An attribute with nothing after the colon, such as description:, asks whether it holds a value. An empty string does not count as set for a string, nor an empty list for a string[]. An operator without its value, such as rtt:>, is still an error.

Entities

There are 13 searchable entity types. Each reads the tables below at the single epoch described under Query Semantics.

EntityReadsEpoch-scoped
serverhx.server_stats + ident and optsYes
clusterhx.server_stats aggregated per clusterYes
accounthx.account_ident + opts, stats and subscription countsIdentity kept, values at the epoch
userhx.user_ident + opts and connection countsIdentity kept, values at the epoch
connectionhx.conn_stats + ident, with account, server and user namesYes
streamhx.stream_replica_stats leader rows + ident and optsYes
kvstoreThe same, for KV-backing streamsYes
objectstoreThe same, for object-store-backing streamsYes
service$SRV.INFO subscriptions in hx.sub_ident, one row per account and service nameYes
consumerhx.consumer_replica_stats leader rows + ident and optsYes
leafhx.leafsYes
routehx.routesYes
gatewayhx.gatewaysYes

Each entity selects every attribute listed for it below; an attribute is never offered without a column behind it.

Attributes

Cross-Entity Attributes

These attributes appear on multiple entities. Using one without an entity qualifier searches all entities that have it.

AttributeTypeserverclusteraccountuserconnectionstreamkvstoreobjectstoreserviceconsumerleafroutegateway
namestringYYYYYYYYY
accountstringYYYYYYY
ipstringYYYYY
clusterstringYYYYYY
rttdurationYYYY
in_msgsintYYYY
out_msgsintYYYY
in_bytesbytesYYYY
out_bytesbytesYYYY
num_subsintYYYY
versionstringYY
descriptionstringYYYY
checkstringYYYYYYYYYY

The check attribute filters entities by check code (for example, check:server-003). It matches against materialized check findings for that entity. On the streams page, a check filter also lists the KV and object-store backing streams the check fired on, so the filtered list matches the stream check's count on the system page.

Server Attributes

AttributeType
idstring
hoststring
coresint
portint
start_timetimestamp
tagsstring[]
git_commitstring
go_versionstring
system_accountstring
config_load_timetimestamp
auth_requiredbool
auth_timeoutduration
tls_requiredbool
tls_verifybool
max_payloadbytes
max_pendingbytes
max_control_lineint
max_connectionsint
ping_intervalduration
ping_maxint
write_deadlineduration
http_hoststring
http_portint
https_portint
http_base_pathstring
leaf_hoststring
leaf_portint
leaf_auth_timeoutduration
leaf_tls_timeoutduration
js_domainstring
js_max_memorybytes
js_max_storebytes
js_store_dirstring
js_sync_intervalduration
js_sync_alwaysbool
js_compress_okbool
js_unique_tagstring
memorybytes
cpufloat
connectionsint
subscriptionsint
routesint
leafsint
gatewaysint
js_memorybytes
js_storagebytes
slow_consumersint
ha_assetsint
total_connectionsint
stale_connectionsint
stalled_clientsint
remotesint
js_reserved_memorybytes
js_reserved_storagebytes
js_api_totalint
js_api_errorsint
js_api_inflightint

Cluster Attributes

AttributeType
clusterstring
serversint
cpufloat
memorybytes
connectionsint
ha_assetsint

servers, cpu, memory, connections and ha_assets are aggregates over the cluster's servers at the epoch, matching the clusters table: servers counts them, cpu averages per-core utilization, and the rest are sums. A cluster result is one row per cluster, not one per server.

Account Attributes

AttributeType
is_systembool
jetstream_enabledbool
connsint
subsint
msgs_sentint
msgs_recvint
leafnodesint
slow_consumersint
expiredbool
completebool
num_exportsint
num_importsint
issuer_keystring
labelstring
tagsstring[]
max_subsint
max_databytes
max_payloadbytes
max_connint
max_leaf_connint
max_importsint
max_exportsint
js_mem_storagebytes
js_disk_storagebytes
js_max_streamsint
js_max_consumersint
js_max_ack_pendingint
last_updatetimestamp
total_connsint
bytes_sentbytes
bytes_recvbytes
route_bytes_sentbytes
route_bytes_recvbytes
route_msgs_sentint
route_msgs_recvint
gateway_bytes_sentbytes
gateway_bytes_recvbytes
gateway_msgs_sentint
gateway_msgs_recvint
leaf_bytes_sentbytes
leaf_bytes_recvbytes
leaf_msgs_sentint
leaf_msgs_recvint

User Attributes

AttributeType
accountstring
bearerbool
name_tagstring
connectionsint
issuer_accountstring
tagsstring[]
last_updatetimestamp

Connection Attributes

AttributeType
kindstring
typestring
langstring
tls_versionstring
uptimeduration
idleduration
bytes_sentbytes
bytes_recvbytes
msgs_sentint
msgs_recvint
pending_bytesbytes
idint
portint
tls_cipherstring
mqtt_clientstring
start_timetimestamp
last_activitytimestamp
stop_timetimestamp
reasonstring
stallsint
serverstring
userstring

Stream Attributes

AttributeType
created_attimestamp
storage_typestring
retention_policystring
max_bytesbytes
max_msgsint
max_ageduration
num_replicasint
is_mirrorbool
discard_policystring
sealedbool
subjectsstring[]
placement_clusterstring
placement_tagsstring[]
max_msg_sizebytes
deny_deletebool
deny_purgebool
allow_directbool
max_consumersint
max_msgs_per_subjectint
deduplication_windowduration
config_first_seqint
discard_new_perbool
allow_rollupbool
no_ackbool
consumer_inactive_thresholdduration
consumer_max_ack_pendingint
mirror_namestring
mirror_api_prefixstring
num_sourcesint
store_compressionstring
has_subject_transformbool
has_republishbool
msgsint
bytesbytes
num_subjectsint
num_consumersint
first_seqint
last_seqint
first_tstimestamp
last_tstimestamp
num_deletedint
mirror_lagint
mirror_activeduration
mirror_errorstring

KV Store Attributes

AttributeType
storage_typestring
num_replicasint
keysint
bytesbytes
historyint
ttlduration
max_bytesbytes
sealedbool
deny_deletebool
deny_purgebool
allow_directbool
store_compressionstring
num_consumersint

Object Store Attributes

AttributeType
storage_typestring
num_replicasint
msgsint
bytesbytes
max_bytesbytes
sealedbool
store_compressionstring
num_consumersint

Service Attributes

AttributeType
service_namestring
instancesint

The services overview aggregates connections into one row per (account, service name), so service also carries the account and check cross-entity attributes. Per-connection attributes such as lang, version, and ip are not exposed here; filter the connection entity for those.

Consumer Attributes

AttributeType
streamstring
created_attimestamp
deliver_policystring
ack_policystring
ack_waitduration
max_deliverint
max_ack_pendingint
inactive_thresholdduration
replay_policystring
heartbeatduration
opt_start_seqint
opt_start_timetimestamp
max_waitingint
max_batchint
max_expiresduration
max_bytesbytes
deliver_subjectstring
deliver_groupstring
flow_controlbool
headers_onlybool
num_replicasint
storage_typestring
filter_subjectsstring[]
sample_frequencystring
memory_storagebool
priority_policystring
num_ack_pendingint
num_redeliveredint
num_waitingint
num_pendingint
delivered_stream_seqint
delivered_consumer_seqint
ack_floor_stream_seqint
ack_floor_consumer_seqint
pausedbool
pause_remainingduration
push_boundbool

Leaf Attributes

AttributeType
is_spokebool
compressionstring
idint
portint
is_isolatedbool
subsstring[]

Route Attributes

AttributeType
uptimeduration
idleduration
pending_sizebytes
did_solicitbool
is_configuredbool
compressionstring
start_timetimestamp
last_activitytimestamp
stallsint

Gateway Attributes

AttributeType
uptimeduration
idleduration
pending_sizebytes
is_outboundbool
is_configuredbool
tls_versionstring
tls_cipherstring
authorized_userstring
start_timetimestamp
last_activitytimestamp
stallsint

Labels

Servers, streams, consumers, KV stores, and object stores carry operator-assigned metadata: the labels set on the NATS resource itself. Because their keys are arbitrary, they are addressed by path rather than listed among the entity's attributes:

metadata.<key>:<value>
metadata.env:prod                        # labeled env=prod
metadata.env:                            # labeled env, whatever the value
metadata.env:!=prod                      # labeled env, but not prod
stream@metadata.io.nats.monitor.enabled:true

A key is matched exactly and is case-sensitive, and dots in a key are part of the key rather than a path into nested JSON: metadata.io.nats.monitor.enabled names one label. Labels are text, so they take the string operators; an ordering operator against one is rejected.

Negation needs the label present: metadata.env:!=prod selects entities labeled with something other than prod, not every entity that is not labeled prod. To include unlabeled entities, negate the whole term with NOT metadata.env:prod.

In a table's filter box, an entity that carries no metadata reports metadata.<key> as an unknown attribute. The global search bar resolves a label term only with an entity qualifier, as in stream@metadata.env:prod; unqualified, it answers that no entities match.

Autocomplete reads label keys and values from the data rather than from a fixed list, ranked by how many entities carry them.

Stages

An expression can end in stages, each introduced by a | with whitespace on both sides, that arrange the rows the filter selected rather than select them:

metadata.env:prod | by region | sort health desc
  • | by <key> groups rows under the value of a label, with an aggregate header per group. Rows without the label group under "no value", last. When several by stages are written, the last one applies.
  • | sort <attr> [desc] orders rows by a column or a label. Sort stages stack left to right, so | sort tier | sort name is a two-level ordering. Anything other than desc sorts ascending.

The Systems and Nodes lists apply stages; a notice under their filter says which stage or attribute it ignored. Entity table filter boxes and their previews drop the stages and apply the filter before them. The global search bar does not accept stages.

A | without surrounding whitespace, as in orders.a|b, is part of the value.

When a value is provided without an attribute or entity qualifier, it is treated as a free-text search. The value is matched (case-insensitive substring via ILIKE) against these attributes on every entity that has at least one of them:

name, service_name, id, cluster, ip, host, version, lang, description, go_version, label, reason, tls_cipher, mqtt_client, js_domain, mirror_name, server, user

For example, searching nats-1 checks the name, id, cluster, ip, host, version, go_version, and js_domain columns on the server entity; the name, cluster, ip, version, lang, reason, tls_cipher, mqtt_client, server, and user columns on the connection entity; and so on for each entity.

Fuzzy Suggestions

When a search query references an unknown entity or attribute name, the system attempts to suggest corrections instead of returning a generic error.

How It Works

  1. The parsed AST is validated against the registry of known entities and attributes.
  2. Unknown names are compared against valid candidates using Levenshtein distance and prefix matching.
  3. The adaptive threshold is max(1, len(name)/3). Shorter names allow fewer edits.
  4. At most 3 suggestions are returned, sorted by edit distance (closest first).

Examples

servr@name:foo    → "Did you mean: server"    (entity misspelling)
nme:foo           → "Did you mean: name"      (attribute misspelling)

Suggestions appear as clickable items in the search dropdown. Clicking a suggestion replaces the query with the corrected version and re-executes the search.

Behavior

  • Suggestions only appear when a query fails to resolve because of an unknown entity or attribute name
  • If no close matches are found, the plain error is shown
  • Valid queries produce normal results with no suggestions

Dropped Filters

A filter naming an attribute the table's entity does not have cannot be turned into a query, and the table falls back to showing every row. A notice under the table's filter box reads Filter not applied followed by the reason, naming the unknown attribute, alongside correction chips drawn from the attributes that particular entity actually has. The same error and suggestions appear in that box's autocomplete as you type.

The whole filter is dropped, not just the offending term. When a single bare word falls back to free-text matching, the notice says so too, so a substring match is never mistaken for an exact one.

This applies to the per-table filter box, which takes unqualified attribute names scoped to that table's entity. The global search bar has no such notice.

Query Semantics

Once parsed into an AST, the search expression is evaluated as follows:

  1. Entity resolution. The parser figures out which entities can satisfy the expression. If a term references a specific entity (for example, server@name:foo), only that entity is queried. If a term references an attribute without an entity, every entity with that attribute is a candidate. Free-text terms match every entity that has at least one free-text attribute. For AND, entity sets are intersected. For OR, they're unioned.

  2. Fan-out. A separate SQL query is generated for each resolved entity. Each query selects the pk and matched columns from the entity's view.

  3. Epoch scoping. The query reads a single epoch: the one the page's time controls resolve to. A live page reads the latest epoch; a pinned or stepped page reads the epoch it is showing, so a search finds what existed then rather than what exists now. Accounts and users are the exception in one direction only: their identity is retained, so one that has stopped reporting is still findable by name, while the values shown beside it are those of the resolved epoch.

  4. Parameterized queries. All user values are passed as parameterized query arguments, not interpolated into SQL.

  5. Result limit. Each entity query returns at most 10 rows, alongside the total number of matches for that entity.

Match Context

Every attribute an expression names is shown beneath each result, in the order it was written, so a row says why it matched:

server@subscriptions:>50000

  nats-east-1    subscriptions: 52,341
  nats-east-2    subscriptions: 51,090
  • Every named attribute appears, not only the ones a given row satisfies. Under OR this tells the two halves apart: a row answering subscriptions:>50000 OR connections:>1000 shows both numbers.
  • A NULL shows as a dash. For NOT js_domain: the absent value is the reason the row matched.
  • Values are formatted by type: counts with thousands separators, sizes in IEC units, durations, and dates.
  • The displayed name is never repeated underneath itself, and a check: term adds nothing, because its value is the code in the term.
  • A free-text match leads. When a bare word matched a column other than the name, that column and value come first.

Values come from the same query that selected the rows, so no extra lookup is made per result.

Table Filter Preview

The per-table filter box shows the first five rows its filter would select, and how many there are, before you press Enter to apply it. It reads the entity's own columns rather than the table's, so attributes the table has no column for still show their values, and it carries the tab's scope and the page's epoch.

Nothing is previewed for a filter the table would not apply; the notice under the input already says why.

Previous
API