Kibana Query Language (KQL) is the default search syntax used across Kibana's Discover, dashboards, and alerts to filter data in Elasticsearch. KQL is simpler than the Lucene query syntax it replaced, parses on the Kibana side, and translates to Elasticsearch DSL behind the scenes. It supports field-scoped queries, boolean operators, wildcards, ranges, and existence checks. KQL is case-insensitive on identifiers (operators, field names) but otherwise treats values exactly as you write them.
Quick Comparison: KQL vs Lucene Query Syntax
| Feature | KQL | Lucene |
|---|---|---|
| Field syntax | field : value |
field:value |
| Free text | Searches the default field | Searches the default field |
| Boolean operators | and, or, not (case-insensitive) |
AND, OR, NOT (must be uppercase) |
| Wildcards | * only (no ?) |
* and ? |
| Regex | Not supported | /pattern/ |
| Fuzzy match | Not supported | term~ or term~N |
| Proximity | Not supported | "phrase"~N |
| Ranges | field > 10 and field < 100 or field : { gte: 10, lt: 100 } |
field:[10 TO 100} |
| Nested fields | First-class (user.name) |
Works via dotted notation |
| Existence | field : * |
_exists_:field |
| Negation | not field : value |
-field:value or NOT field:value |
In Kibana, toggle between KQL and Lucene via the gear icon next to the search bar. KQL is the default since Kibana 7.0. Use Lucene only when you specifically need regex, fuzzy match, or proximity search.
KQL Syntax
Free-Text Search
Searches the default field configured on the data view:
error
Field-Scoped Search
status : "error"
service.name : "checkout"
Whitespace around the colon is optional but conventional. Field values with spaces or special characters need quotes: host : "web-01.prod".
Boolean Operators
status : "error" and user : "admin"
status : "error" or status : "warning"
not status : "success"
Operators are case-insensitive (and, AND, And all work). Parentheses group expressions:
(status : "error" or status : "warning") and user : "admin"
Wildcards
KQL supports * (zero or more characters) but not ? (single character):
user : john*
service.name : *checkout*
host : web-*-prod
Leading wildcards (*name) are allowed but slow because they prevent Elasticsearch from using the inverted index efficiently.
Range Queries
age >= 30 and age < 50
response_time > 1000
@timestamp > "2025-01-01T00:00:00Z"
Comparison operators: >, >=, <, <=. KQL does not have an inclusive-exclusive range like Lucene's [a TO b}.
Existence Checks
field_name : *
The _exists_ syntax that worked in earlier Kibana versions is deprecated in KQL; use field : * instead.
Nested Fields
KQL treats nested field references natively:
products.name : "widget"
For documents indexed as nested type, use the explicit nested syntax:
products : { name : "widget" and price > 50 }
The nested form enforces that both conditions match within the same nested document, which dotted notation does not.
What KQL Cannot Do
KQL is intentionally limited. Things that require dropping to Lucene or to raw Elasticsearch DSL:
- Regex matching. KQL has no regex; Lucene supports
/pattern/. - Fuzzy matching. No edit-distance match.
- Proximity search. No
"phrase"~3. - Boosting. No
term^2.5. - Single-character wildcard. No
?operator. - Span queries. Use Elasticsearch DSL.
When you need any of these, switch the search bar to Lucene mode or build a saved query / filter via the filter UI (which renders to DSL).
KQL Performance Considerations
KQL parses on the Kibana node and translates to Elasticsearch query DSL. The query that hits Elasticsearch is what matters for performance, not the KQL syntax. A few patterns to avoid:
- Leading wildcards (
*term) force a full-term scan. They're not blocked, but they don't use the inverted index efficiently. - Wildcards on high-cardinality fields (request IDs, UUIDs) blow up term-expansion cost.
notagainst very broad sets can be expensive; prefer constraining the positive side first.- Range queries on text fields are not directly supported - cast the field to a date or numeric type at index time.
Operating Kibana and Elasticsearch in Production
KQL is the entry point to data, but the cluster underneath does the work. When a Kibana dashboard times out at the default 30-second limit (see Kibana request timeout after 30000ms), the cause is almost always on the Elasticsearch side: a slow shard, JVM pressure, hot node, or query that touches too much data.
Pulse monitors Elasticsearch and OpenSearch clusters with AI-powered root-cause analysis. When a KQL-backed dashboard slows down, Pulse identifies the specific shard, node, or aggregation responsible, rather than just paging on the symptom.
Frequently Asked Questions
Q: What's the difference between KQL and Lucene in Kibana?
A: KQL is Kibana's default, simpler search syntax for filtering Elasticsearch data. Lucene is the older, more permissive query syntax that supports regex, fuzzy match, proximity search, and boosting. Switch between them via the gear icon next to the search bar. Use KQL by default; use Lucene only when you need its specialized features.
Q: Does KQL support regex?
A: No. KQL has no regex operator. For regex matching, switch to Lucene mode (/pattern/) or use a runtime field with a Painless script.
Q: Is KQL case-sensitive?
A: Operators (and, or, not) and field names are case-insensitive. Field values are passed to Elasticsearch as-is, so case sensitivity on values depends on the field's analyzer. A keyword field with no normalizer is case-sensitive; a text field with the standard analyzer is lowercased at index time.
Q: How do I search for documents missing a field in KQL?
A: Use not field : *. KQL deprecated the _exists_ operator; field : * checks for existence, and not field : * checks for absence.
Q: Can I do fuzzy search in KQL?
A: No. KQL doesn't support fuzzy matching. Switch to Lucene syntax (term~) for edit-distance matching, or use a match query with fuzziness parameter via the filter UI.
Q: Why is my KQL wildcard query slow?
A: Leading wildcards (*term) and wildcards on high-cardinality fields (UUIDs, request IDs) prevent Elasticsearch from using the inverted index efficiently. Prefer trailing wildcards (term*), narrow the search field, and use keyword fields appropriately.
Related Reading
- What is Kibana Dashboard: how filters and KQL drive dashboards
- How to Create a Kibana Dashboard: use KQL inside dashboards
- Kibana Request Timeout After 30000ms: when filtered queries time out
- What is Elasticsearch Mapping: how field types affect KQL behavior
- What is an Elasticsearch Analyzer: why case sensitivity depends on the analyzer