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,namematches 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.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
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, andNOT. - Without an explicit operator, adjacent terms are implicitly ANDed.
- Grouping with parentheses
()overrides default precedence. - Precedence (lowest to highest):
OR<AND<NOT. ANDandORare case-sensitive keywords (must be uppercase).
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.
| Unit | Suffix |
|---|---|
| Nanosecond | ns |
| Microsecond | us, µs |
| Millisecond | ms |
| Second | s |
| Minute | m |
| Hour | h |
| Day | d |
bytes
A number with a byte size unit suffix (IEC binary units, powers of 1024). Supports the same operators as int.
| Unit | Suffix |
|---|---|
| Byte | b |
| Kibibyte | kib |
| Mebibyte | mib |
| Gibibyte | gib |
| Tebibyte | tib |
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.
| Operator | Syntax | string | string[] | int | float | duration | bytes | timestamp | bool |
|---|---|---|---|---|---|---|---|---|---|
| Equal | (implicit) | Y | Y | Y | Y | Y | Y | Y | Y |
| Not equal | != | Y | Y | Y | Y | Y | Y | Y | Y |
| Greater than | > | Y | Y | Y | Y | Y | |||
| Greater or equal | >= | Y | Y | Y | Y | Y | |||
| Less than | < | Y | Y | Y | Y | Y | |||
| Less or equal | <= | Y | Y | Y | Y | Y | |||
| Between | .. | Y | Y | Y | Y | Y | |||
| Like | ~ | Y | Y |
String equality (=) is case-insensitive (ILIKE). The ~ operator performs an ILIKE substring match.
Entities
There are 13 searchable entity types. Each entity maps to a database view and is scoped to the latest epoch where applicable.
| Entity | View | Epoch-scoped |
|---|---|---|
server | hx.servers | Yes |
cluster | hx.server_ident | No |
account | hx.account_ident | No |
user | hx.user_ident | No |
connection | hx.conns | Yes |
stream | hx.streams | Yes |
kvstore | hx.streams | Yes |
objectstore | hx.streams | Yes |
service | hx.services | Yes |
consumer | hx.consumers | Yes |
leaf | hx.leafs | Yes |
route | hx.routes | Yes |
gateway | hx.gateways | Yes |
Attributes
Cross-Entity Attributes
These attributes appear on multiple entities. Using one without an entity qualifier searches all entities that have it.
| Attribute | Type | server | cluster | account | user | connection | stream | kvstore | objectstore | service | consumer | leaf | route | gateway |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
name | string | Y | Y | Y | Y | Y | Y | Y | Y | Y | ||||
account | string | Y | Y | Y | Y | Y | Y | Y | ||||||
ip | string | Y | Y | Y | Y | Y | ||||||||
cluster | string | Y | Y | Y | Y | Y | ||||||||
rtt | duration | Y | Y | Y | Y | |||||||||
in_msgs | int | Y | Y | Y | Y | |||||||||
out_msgs | int | Y | Y | Y | Y | |||||||||
in_bytes | bytes | Y | Y | Y | Y | |||||||||
out_bytes | bytes | Y | Y | Y | Y | |||||||||
num_subs | int | Y | Y | Y | Y | |||||||||
version | string | Y | Y | Y | ||||||||||
description | string | Y | Y | Y | Y | |||||||||
check | string | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
The check attribute filters entities by check code (for example, check:SERVER_003). It matches against materialized check results for that entity.
Server Attributes
| Attribute | Type |
|---|---|
id | string |
host | string |
cores | int |
port | int |
start_time | timestamp |
tags | string[] |
git_commit | string |
go_version | string |
system_account | string |
config_load_time | timestamp |
auth_required | bool |
auth_timeout | duration |
tls_required | bool |
tls_verify | bool |
max_payload | bytes |
max_pending | bytes |
max_control_line | int |
max_connections | int |
ping_interval | duration |
ping_max | int |
write_deadline | duration |
http_host | string |
http_port | int |
https_port | int |
http_base_path | string |
leaf_host | string |
leaf_port | int |
leaf_auth_timeout | duration |
leaf_tls_timeout | duration |
js_domain | string |
js_max_memory | bytes |
js_max_store | bytes |
js_store_dir | string |
js_sync_interval | duration |
js_sync_always | bool |
js_compress_ok | bool |
js_unique_tag | string |
memory | bytes |
cpu | float |
connections | int |
subscriptions | int |
routes | int |
leafs | int |
gateways | int |
js_memory | bytes |
js_storage | bytes |
slow_consumers | int |
ha_assets | int |
total_connections | int |
stale_connections | int |
stalled_clients | int |
remotes | int |
js_reserved_memory | bytes |
js_reserved_storage | bytes |
js_api_total | int |
js_api_errors | int |
js_api_inflight | int |
Cluster Attributes
| Attribute | Type |
|---|---|
cluster | string |
servers | int |
cpu | float |
memory | bytes |
connections | int |
ha_assets | int |
Cluster attributes (servers, cpu, memory, connections, ha_assets) are computed aggregates.
Account Attributes
| Attribute | Type |
|---|---|
is_system | bool |
jetstream_enabled | bool |
conns | int |
subs | int |
msgs_sent | int |
msgs_recv | int |
leafnodes | int |
slow_consumers | int |
expired | bool |
complete | bool |
num_exports | int |
num_imports | int |
issuer_key | string |
label | string |
tags | string[] |
max_subs | int |
max_data | bytes |
max_payload | bytes |
max_conn | int |
max_leaf_conn | int |
max_imports | int |
max_exports | int |
js_mem_storage | bytes |
js_disk_storage | bytes |
js_max_streams | int |
js_max_consumers | int |
js_max_ack_pending | int |
last_update | timestamp |
total_conns | int |
bytes_sent | bytes |
bytes_recv | bytes |
route_bytes_sent | bytes |
route_bytes_recv | bytes |
route_msgs_sent | int |
route_msgs_recv | int |
gateway_bytes_sent | bytes |
gateway_bytes_recv | bytes |
gateway_msgs_sent | int |
gateway_msgs_recv | int |
leaf_bytes_sent | bytes |
leaf_bytes_recv | bytes |
leaf_msgs_sent | int |
leaf_msgs_recv | int |
User Attributes
| Attribute | Type |
|---|---|
account | string |
bearer | bool |
name_tag | string |
connections | int |
issuer_account | string |
tags | string[] |
last_update | timestamp |
Connection Attributes
| Attribute | Type |
|---|---|
kind | string |
type | string |
lang | string |
tls_version | string |
uptime | duration |
idle | duration |
bytes_sent | bytes |
bytes_recv | bytes |
msgs_sent | int |
msgs_recv | int |
pending_bytes | bytes |
id | int |
port | int |
tls_cipher | string |
mqtt_client | string |
start_time | timestamp |
last_activity | timestamp |
stop_time | timestamp |
reason | string |
stalls | int |
Stream Attributes
| Attribute | Type |
|---|---|
created_at | timestamp |
storage_type | string |
retention_policy | string |
max_bytes | bytes |
max_msgs | int |
max_age | duration |
num_replicas | int |
is_mirror | bool |
discard_policy | string |
sealed | bool |
subjects | string[] |
placement_cluster | string |
placement_tags | string[] |
max_msg_size | bytes |
deny_delete | bool |
deny_purge | bool |
allow_direct | bool |
max_consumers | int |
max_msgs_per_subject | int |
deduplication_window | duration |
config_first_seq | int |
discard_new_per | bool |
allow_rollup | bool |
no_ack | bool |
consumer_inactive_threshold | duration |
consumer_max_ack_pending | int |
mirror_name | string |
mirror_api_prefix | string |
num_sources | int |
store_compression | string |
has_subject_transform | bool |
has_republish | bool |
msgs | int |
bytes | bytes |
num_subjects | int |
num_consumers | int |
first_seq | int |
last_seq | int |
first_ts | timestamp |
last_ts | timestamp |
num_deleted | int |
mirror_lag | int |
mirror_active | duration |
mirror_error | string |
KV Store Attributes
| Attribute | Type |
|---|---|
storage_type | string |
num_replicas | int |
keys | int |
bytes | bytes |
history | int |
ttl | duration |
max_bytes | bytes |
sealed | bool |
deny_delete | bool |
deny_purge | bool |
allow_direct | bool |
store_compression | string |
num_consumers | int |
Object Store Attributes
| Attribute | Type |
|---|---|
storage_type | string |
num_replicas | int |
msgs | int |
bytes | bytes |
max_bytes | bytes |
sealed | bool |
store_compression | string |
num_consumers | int |
Service Attributes
| Attribute | Type |
|---|---|
service_name | string |
instances | int |
lang | string |
version | string |
ip | string |
Consumer Attributes
| Attribute | Type |
|---|---|
stream | string |
created_at | timestamp |
deliver_policy | string |
ack_policy | string |
ack_wait | duration |
max_deliver | int |
max_ack_pending | int |
inactive_threshold | duration |
replay_policy | string |
heartbeat | duration |
opt_start_seq | int |
opt_start_time | timestamp |
max_waiting | int |
max_batch | int |
max_expires | duration |
max_bytes | bytes |
deliver_subject | string |
deliver_group | string |
flow_control | bool |
headers_only | bool |
num_replicas | int |
storage_type | string |
filter_subjects | string[] |
sample_frequency | string |
memory_storage | bool |
priority_policy | string |
num_ack_pending | int |
num_redelivered | int |
num_waiting | int |
num_pending | int |
delivered_stream_seq | int |
delivered_consumer_seq | int |
ack_floor_stream_seq | int |
ack_floor_consumer_seq | int |
paused | bool |
pause_remaining | duration |
push_bound | bool |
Leaf Attributes
| Attribute | Type |
|---|---|
is_spoke | bool |
compression | string |
id | int |
port | int |
is_isolated | bool |
subs | string[] |
Route Attributes
| Attribute | Type |
|---|---|
uptime | duration |
idle | duration |
pending_size | bytes |
did_solicit | bool |
is_configured | bool |
compression | string |
start_time | timestamp |
last_activity | timestamp |
stalls | int |
Gateway Attributes
| Attribute | Type |
|---|---|
uptime | duration |
idle | duration |
pending_size | bytes |
is_outbound | bool |
is_configured | bool |
tls_version | string |
tls_cipher | string |
authorized_user | string |
start_time | timestamp |
last_activity | timestamp |
stalls | int |
Free-Text Search
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, id, cluster, ip, host, version, lang, description, go_version, label, reason, tls_cipher, mqtt_client, js_domain, mirror_name
For example, searching nats-1 checks the name, id, cluster, ip, host, and version columns on the server entity; the name, ip, version, and lang 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
- The parsed AST is validated against the registry of known entities and attributes.
- Unknown names are compared against valid candidates using Levenshtein distance and prefix matching.
- The adaptive threshold is
max(1, len(name)/3). Shorter names allow fewer edits. - 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)
server@nme:foo → "Did you mean: name" (scoped 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
GenerateQueriesfails due to unknown names - If no close matches are found, the original error is shown
- Valid queries produce normal results with no suggestions
Query Semantics
Once parsed into an AST, the search expression is evaluated as follows:
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. ForAND, entity sets are intersected. ForOR, they're unioned.Fan-out. A separate SQL query is generated for each resolved entity. Each query selects the
pkand matched columns from the entity's view.Epoch scoping. For epoch-scoped entities, the query is filtered to the latest epoch (for example,
epoch = (SELECT MAX(epoch) FROM hx.server_stats)). That makes sure results reflect the most recent data collection.Parameterized queries. All user values are passed as parameterized query arguments, not interpolated into SQL.
Result limit. Each entity query is capped at
LIMIT 100.