Nexthink Query Language

The NQL Guide

NQL is the query language that powers custom investigations, dashboard widgets, and Flow workflow triggers in Nexthink Infinity. It reads like SQL but is purpose-built for the Nexthink data model: you query entities like devices, users, packages, and events rather than database tables. This guide covers what you need to write the queries that matter, not a complete language reference.

SQL-like
Familiar syntax if you know SQL: purpose-built for endpoint data
Real-time
Queries run against live Collector data: results in seconds
Workspace
Workspace translates natural language into NQL: use it to learn the syntax
Widgets
Every custom dashboard widget is backed by an NQL query

The Right Way to Learn NQL

The fastest way to learn NQL is not to read the reference documentation first: it's to use Workspace. Ask Workspace a question in plain English, see the NQL it generates, run the query, then modify the NQL to understand what each part does. You'll learn more in 20 minutes of this pattern than in an hour of reading syntax definitions.

Workspace as an NQL tutor: Type "Show me all devices where available disk space is below 10GB" into Workspace. It generates the NQL, runs it, and shows you the results. Now look at the query: you can see exactly how it expressed that condition. Modify the threshold to 20GB and run it again. This iteration loop is the most efficient path from "I don't know NQL" to "I can write the queries I need."

Key Entities in NQL

NQL queries run against entities: the core objects in the Nexthink data model. Understanding which entity to query determines what data you can access and how you can aggregate it. These are the entities you'll use in almost every investigation.

device

The primary entity. Represents an individual managed endpoint. Contains hardware specs, OS, performance metrics, DEX score, collector status, and device-level events.

device
user

The employee or user assigned to a device. Contains identity attributes from the directory: name, email, department, location, job title.

user
package

Software installed on devices. Represents individual applications or packages with version, publisher, and installation status per device.

package
execution

An individual application execution event: when a specific application was launched on a specific device. Contains timing, performance data, and crash status.

execution
connection

Network connection events. Represents network activity from a device: connection quality, throughput, latency, and destination information.

connection
alert

Platform alerts triggered by threshold conditions or anomaly detection. Contains alert type, severity, affected device, and timestamp.

alert
campaign_event

Engage campaign interactions: responses to surveys, notification acknowledgements, campaign delivery events.

campaign_event
remote_action

Flow (formerly Remote Action) execution records. Contains workflow name, trigger, execution status, and output per device.

remote_action
event

Generic endpoint events: BSODs, login events, policy changes, security detections. The most granular layer of Collector data.

event

NQL Syntax Fundamentals

NQL follows a SELECT → FROM → WHERE → AGGREGATE structure similar to SQL. The key difference is that you're always selecting from an entity type, and your field names come from the Nexthink data schema for that entity.

Basic query structure
Basic SELECT
select (device.name, device.os.version, device.dex.score)
from device
Filtering with WHERE
select (device.name, device.os.version, device.storage.free.ratio)
from device
where device.storage.free.ratio < 0.10  -- less than 10% free disk
Multiple conditions
select (device.name, user.department, device.dex.score)
from device
where device.dex.score < 5.0
  and user.department == "Finance"
Aggregation and counting
Count devices by condition
select (count())
from device
where device.collector.status == "online"
Group by and count
select (user.department, count())
from device
where device.dex.score < 5.0
aggregate by user.department
Average metric by group
select (user.department, avg(device.dex.score))
from device
aggregate by user.department
sort by avg(device.dex.score) asc  -- worst first
Time filters
Last N days
select (device.name, count())
from execution
where execution.status == "crashed"
  and execution.start > date() - days(7)  -- last 7 days
aggregate by device.name
sort by count() desc
limit 20
Cross-entity queries (joins)
Query packages installed on devices in a department
select (package.name, package.version, count())
from package
where user.department == "Engineering"
  and package.publisher == "Microsoft"
aggregate by (package.name, package.version)
sort by count() desc

Queries for Common IT Scenarios

These are the queries that come up most often in Nexthink investigations. Use them directly, or use them as starting points to modify for your environment. Every query here can be run in Workspace or pasted into a custom dashboard widget.

Fleet health
Devices with lowest DEX scores
select (device.name, user.display.name, user.department, device.dex.score)
from device
where device.collector.status == "online"
  and device.dex.score < 5.0
sort by device.dex.score asc
limit 50
Collector coverage by department
select (user.department, count())
from device
where device.collector.status == "offline"
aggregate by user.department
sort by count() desc
Application performance
Most-crashed applications in the last 30 days
select (execution.application.name, count())
from execution
where execution.status == "crashed"
  and execution.start > date() - days(30)
aggregate by execution.application.name
sort by count() desc
limit 10
Devices with Teams crashes this week
select (device.name, user.display.name, count())
from execution
where execution.application.name == "Microsoft Teams"
  and execution.status == "crashed"
  and execution.start > date() - days(7)
aggregate by (device.name, user.display.name)
sort by count() desc
Security and compliance
Devices missing a required application
select (device.name, user.department, user.display.name)
from device
where device.os.type == "windows"
  and not exists (
    select () from package
    where package.name == "CrowdStrike Falcon Sensor"
  )
sort by user.department asc
Devices with outdated OS version
select (device.name, device.os.version, user.department)
from device
where device.os.type == "windows"
  and device.os.version != "Windows 11"
sort by device.os.version asc
Software and license management
Unused software: installed but not launched in 90 days
select (package.name, package.version, count())
from package
where package.last.execution.date < date() - days(90)
  and package.publisher == "Adobe"  -- target specific vendor
aggregate by (package.name, package.version)
sort by count() desc
Devices with multiple versions of the same application
select (device.name, package.name, package.version)
from package
where package.name like "%Microsoft 365%"
sort by (device.name, package.version) asc

Tips That Matter in Practice

Always filter on collector status

Add device.collector.status == "online" to device queries unless you specifically want offline devices. Offline devices often have stale data that will skew your results: a device that went offline 3 months ago still shows its last-known DEX score.

Use explicit time windows

Many entities accumulate historical data. Without a time filter, execution queries return all execution events ever. Always add a where execution.start > date() - days(N) filter. Without it, large environments will time out or return millions of rows.

Use LIMIT on exploratory queries

When exploring data, add limit 100 to your queries while you're validating the logic. Remove the limit once you're confident the query is correct. This prevents accidentally querying the entire fleet and waiting a minute for 50,000 rows.

Ask Workspace first, then refine

Workspace-generated NQL is correct but sometimes verbose. Use it as a starting point, then simplify: remove fields you don't need, tighten time windows, add aggregations. The generated query shows you the correct field names even if you rewrite the logic.

Test field names before building widgets

NQL field names are case-sensitive and must match the schema exactly. Run a simple SELECT with the fields you want before building a dashboard widget. A widget that fails to load because of a typo in a field name is frustrating to debug under time pressure.

Prefer aggregated queries for dashboards

Dashboard widgets that return 10,000 device rows are slow to load and useless to read. Design dashboard queries to return aggregated values, counts, averages, percentages,not row-level data. Row-level data belongs in on-demand investigations, not persistent widgets.

Related Topics

Workspace translates plain language into NQL and is the fastest way to explore the data model. The Use Cases guide shows how NQL-backed investigations combine with Flow and Engage to create complete DEX programs.

Use Cases Workspace Dashboards Flow

NQL syntax examples on this page reflect the Nexthink Infinity platform. Field names and syntax may evolve: consult the official Nexthink documentation for the current schema reference. View full references →