FlatQL
Sign in Start free

Limits, caps and unsupported SQL

Every cap in one place, with the reason for it and the way around it. Most of them stop mattering once the WHERE clause is something the cluster can apply.

Engine limits#

Limit Value Where it applies
Rows fetched per index per statement 50,000 Any index (or pattern) that has to be scanned because the statement is not fully pushable
Groups per pushed GROUP BY 50,000 A GROUP BY run as a composite aggregation; pages of 1,000 buckets
Join keys sent to the other side 50,000 Equi-joins where one side was fetched first; above that the other side is scanned
Scroll page size 5,000 rows, 4 parallel slices Full scans
Rows shown in the worksheet 500 The result grid; raise LIMIT or use Download for more
Export 5,000,000 rows Download of a statement, any format
Field-type cache 5 minutes _field_caps per connection and index; mapping changes appear after that
Statement timeout against the cluster 120 seconds per request Each search, scroll page and aggregation request

The engine source states the fetch rule plainly:

Otherwise the index is scanned up to the fetch cap and the response carries a warning.

"Otherwise" means: the WHERE was not pushed in full, or the statement has a DISTINCT, window function, QUALIFY or an aggregate the cluster cannot run. The result then shows a note such as "orders has 1,284,201 matching documents; only the first 50,000 were scanned", and the Show as DSL tab shows the request in mode scroll (up to 50,000 rows). The pushdown rules on the pushdown page tell you how to get back to a bounded search or an aggregation.

Two consequences worth knowing:

  • An index pattern counts as one index. logs-* across a month of daily indices shares one 50,000-row cap.
  • A self-join fetches the same index twice, once per alias, each with its own cap.

Aggregation limits#

A pushed GROUP BY stops after 50,000 groups and adds a note. Statements with a high-cardinality key (a user id, an order id) hit this; aggregate at a coarser level or filter first. COUNT(DISTINCT x) is computed by the cluster's cardinality aggregation and is approximate, about 1 percent off at large counts; the result says so. APPROX_COUNT_DISTINCT is the honest name for the same thing. MEDIAN, PERCENTILE_CONT, APPROX_PERCENTILE, APPROX_TOP_K, LISTAGG and ARRAY_AGG are computed in the engine over a scan, so the 50,000-row cap applies to them.

Export limits#

Downloads stream to disk as they are produced, in CSV, TSV, JSON, NDJSON, Excel or Parquet, up to 5,000,000 rows. A plain projection over one index with the whole WHERE pushed (SELECT a, b FROM orders WHERE status = 'paid' ORDER BY placed_at) streams straight from the cluster with no 50,000-row cap. Anything that needs the engine, such as a join, a window function or a GROUP BY the cluster cannot run, runs through the engine first and inherits the per-index cap. The export page has the formats and the CSV export walkthrough shows a 5,000,000-row run.

Unsupported SQL#

Construct Status Use instead
MATCH_RECOGNIZE not supported LAG / LEAD / ROW_NUMBER with QUALIFY
Time Travel (AT, BEFORE) not available; Elasticsearch keeps only the current document a snapshot index or a date field
Stored procedures, CALL, EXECUTE IMMEDIATE not available a worksheet with several statements
INSERT, UPDATE, DELETE, CREATE TABLE not run by the engine; only SELECT and WITH an Elasticsearch request (PUT, POST, DELETE) in the same worksheet
ORDER BY _score no score is computed; MATCH is a filter an Elasticsearch request with a match query
Elasticsearch nested query semantics not generated by the engine LATERAL FLATTEN then filter, or an Elasticsearch request

Statements that are not read-only are rejected with "Only read-only SELECT statements run here". Writes typed as Elasticsearch requests are still subject to the connection's read-only flag, wildcard-delete protection and destructive-operation confirmations.

Cluster SQL limits#

In Cluster SQL mode the statement is executed by x-pack SQL or the OpenSearch SQL plugin, and their rules apply: no joins or subqueries, aggregations limited to GROUP BY on keyword or numeric fields with COUNT, SUM, AVG, MIN, MAX, no sorting or grouping on text fields without the keyword sub-field, and the indices:data/read/sql privilege on the user. Results are not paginated beyond the LIMIT you write. When the cluster rejects a statement for a syntax or feature reason, FlatQL runs it in Full SQL and says so in the result notes.

Plan limits#

Free Pro ($199 once, per user)
Clusters 1 unlimited
Worksheets 1 unlimited
Query history 1 day everything
Export and Download no yes, up to 5,000,000 rows
Load data (CSV, Excel, JSON, API) no yes
Saved queries no yes
Ask FlatQL 20 questions a day, shown in the panel no displayed limit; a fair-use cap applies and the panel offers "Raise a limit request" when it is reached
SQL engine, Show as DSL, MATCH, index patterns, FLATTEN yes yes

The Free plan runs the full engine on one cluster; the caps in this page are the same on both plans. Prices and what the licence covers are on pricing and pricing and licensing. For the limits of SQL on Elasticsearch in general, rather than of FlatQL, see Elasticsearch SQL limitations.

Questions

Why is my result marked truncated?

The engine scanned the first 50,000 matching documents of an index and there were more. Add filters the cluster can apply (=, IN, ranges, LIKE on keyword fields, MATCH) or a LIMIT, or use a GROUP BY the cluster can aggregate.

Can I raise the 50,000-row cap?

Not from the worksheet. Exports of plain projections are not bound by it, so for a large extract use Download instead of scrolling the grid.

Last updated 2026-11-04

Guides

How FlatQL handles the jobs Elasticsearch makes hard.