Cube Core version 1.8 is the latest release to date. It brings mistake-proof defaults: development mode is now opt-in, query values are redacted from logs, and validation of data models and requests is stricter. It also improves performance: result streaming in the SQL API is up to 1.76x faster, Cube Store performance toggles are on by default, and the SQL API pushes UNION queries down to the data source.

Headline features in this release:

  • Breaking changes: development mode is opt-in, the cube.ts configuration file is removed, and data models with an empty member_level or several joins to the same cube no longer compile
  • New in APIs and client libraries: UNION pushdown, COPY ... FROM STDIN, and pushdown of window functions and more aggregate functions in the SQL API
  • New in data modeling: memo() to cache the results of API calls across compile stages
  • Performance: up to 1.76x faster result streaming in the SQL API, and Cube Store performance toggles on by default

This release contains breaking changes. Most of them first shipped in v1.7.34 through v1.7.48, so if you already run a recent v1.7.x release, you may have applied some of them. Before upgrading, please familiarize yourself with the breaking changes and upgrade considerations below.

Breaking changes

BREAKING: Development mode is opt-in. Previously, Cube enabled development mode whenever NODE_ENV was anything but production. An instance with neither NODE_ENV nor CUBEJS_DEV_MODE set came up in development mode, which turns off access control checks. Now development mode is decided by CUBEJS_DEV_MODE alone, defaults to false, and NODE_ENV is ignored. If you rely on development mode locally, set CUBEJS_DEV_MODE=true. The cubejs dev-server command still turns it on for itself. This change first shipped in v1.7.47. Read more in the documentation: CUBEJS_DEV_MODE, Deployment.

BREAKING: The cube.ts configuration file is removed. Cube no longer loads a configuration file written in TypeScript. Move your configuration to cube.js or cube.py. This change first shipped in v1.7.34. Read more in the documentation: Configuration options.

BREAKING: member_level in access policies requires includes or excludes. Previously, an empty member_level silently gave access to every member of the cube, the opposite of how an empty block reads. Now such a data model fails to compile. Use includes: "*" to give access to all members, or list them explicitly. This change first shipped in v1.7.48. Read more in the documentation: Data access policies.

BREAKING: Several joins to the same cube are a compile error. Previously, a cube could declare more than one join to the same cube, and Cube silently kept only the last one, so queries used a join path that the author didn't write. Now such a data model fails to compile. To join the same table through two different keys, use extends to create a second cube over it and join that. This change first shipped in v1.7.40. Read more in the documentation: Joins.

BREAKING: @cubejs-client/ngx requires Angular 20 or later. The Angular client library now targets Angular 20 LTS. Upgrade your application to Angular 20 before you upgrade the library. This change first shipped in v1.7.41. Read more in the documentation: Angular.

Upgrade considerations

These changes don't break a correctly configured deployment, but they can change what you see after the upgrade:

  • IMPORTANT: Log redaction is on by default outside development mode. Filter values, SQL parameters, and string literals in SQL API statements are replaced with redacted in logs, so personal data passed in queries doesn't end up in log storage. Set CUBEJS_LOG_REDACTION=false to keep the original values.
  • IMPORTANT: Cube Store performance toggles are on by default. See Performance optimizations below.
  • Only IANA time zone names, such as America/Los_Angeles, are accepted as a query time zone. Other values are rejected.
  • An invalid x-request-id header now returns a 400 error. Read more about the allowed values.
  • The /v1/graphql-to-json endpoint requires the meta API scope.
  • Parameters of pre-aggregation queries and over-long date ranges are validated more strictly; an over-long date range returns a 400 error instead of a 500 error.
  • @cubejs-client/core uses the built-in fetch instead of cross-fetch, so it needs a runtime with a global fetch, such as Node.js 18 or later.
  • cubejs create no longer has the --template option.

Deprecations

DEPRECATED: The cubejs CLI. The cubejs CLI (the cubejs-cli npm package) is deprecated in favor of the new Cube CLI. It now prints a deprecation warning; set CUBEJS_CLI_NO_DEPRECATION_WARNING=true to hide it. Read more in the documentation: Continuous deployment, CUBEJS_CLI_NO_DEPRECATION_WARNING.

DEPRECATED: The Hive driver. The Hive driver is deprecated as of v1.7.25 and will be removed in a future release. Read more in the documentation: Hive.

New in data modeling

Caching across compile stages with memo(). A data model compiles in several stages, and each stage runs the model files again, asyncModule() callbacks included. Previously, an API call inside asyncModule() ran once per stage. Now you can wrap it in memo(): the function runs once per compilation, and every later call gets the stored result back.

asyncModule(async () => {
const cubes = await memo('dynamic_cubes', async () => (await fetch(url)).json());
cubes.forEach((cube) => {
// ...
});
});

Read more in the documentation: Dynamic data models, Execution environment.

This release also adds segments in FILTER_PARAMS, calendar time shifts in FILTER_PARAMS, and primary key detection when a data model is generated from tables, contributed by @haechangcho.

New in data source support

Query attribution in BigQuery, ClickHouse, Presto, and Trino. Now Cube tags the queries it runs with the request ID, so you can match a query in the data source's own logs with the API request that caused it. In BigQuery, the query jobs of a request carry a cube_request_id label. In ClickHouse, the request ID is the query_id. In Presto and Trino, it is the trace token. Read more in the documentation: BigQuery, ClickHouse, Presto, Trino.

This release also adds Tesseract support for Apache Pinot, contributed by @seanm-stripe, with type detection and SQL dialect fixes; Tesseract support for QuestDB; query cancellation for Snowflake; support for TIMESTAMP_TZ and TIMESTAMP_LTZ in Snowflake, contributed by @npwalker; a migration of the DuckDB driver to @duckdb/node-api; and named ESM exports for all drivers.

New in APIs and client libraries

UNION pushdown in the SQL API. Previously, the SQL API always ran UNION in query post-processing, on top of queries that the row limit had already truncated. A query such as SELECT DISTINCT ... UNION SELECT DISTINCT ... could then return results with values silently missing. Now, if all SELECT statements query cubes of the same data source, the SQL API pushes the whole union down to that data source. The row limit then applies to the result of the union, and filters and projections over the union are pushed down too.

SELECT DISTINCT status AS value
FROM orders
UNION
SELECT DISTINCT city AS value
FROM users;

A union across data sources, or in Druid, ksqlDB, or SQLite, still runs in post-processing. Read more in the documentation: SQL API reference.

COPY ... FROM STDIN in the SQL API. Now you can load data from the client into a temporary table with COPY ... FROM STDIN, in the text or CSV format, the same way as in PostgreSQL. Then you can query it alongside your cubes. Read more in the documentation: SQL API reference.

More functions in the SQL API. Now the SQL API pushes down the ranking and value window functions, such as ROW_NUMBER, RANK, DENSE_RANK, and FIRST_VALUE, to the data source. Previously, it computed them in post-processing over a row-limited result. It also pushes down multi-argument aggregate functions, such as APPROX_PERCENTILE_CONT, in Presto, Trino, and Amazon Athena, and supports STRING_AGG, WIDTH_BUCKET, and pushdown of DATE_ADD. Read more in the documentation: Window functions.

The SQL API also gains: SELECT DISTINCT ON, regtype casts, date-only strings parsed as timestamps, pushdown for views whose members span several data sources, a preference for pushdown over post-processing without a row limit with an option to fail such queries, a separate row limit for non-streaming queries, and a batch size limit for scans.

The REST and GraphQL APIs also gain usedPreAggregations in REST API and GraphQL API responses, so you can tell which pre-aggregations served a query.

The client libraries also gain an onlyViews option for meta(), a timezone option for cubeSql() and cubeSqlStream(), and usedPreAggregations on cubeSql() results.

New in pre-aggregations

This release adds matching of time-shifted measures against pre-aggregations, and matching of pre-aggregations that don't store the dimensions of a calculation group.

New in query orchestrator

This release adds a fast track for queries in the queue and local evaluation of interval refresh keys, which honors refreshKeyRenewalThreshold.

New in Cube Store

This release adds server-side encryption for S3, the SYS CACHESTORE WIPE and TRUNCATE commands, a limit on WebSocket connections per user, limits on concurrent and queued query planning, a configurable Kafka lag timeout for streaming, and a maximum message size for the connection between Cube and Cube Store.

New in configuration

This release adds limits that make Cube report an error instead of crashing on a query or a data model that is too deep: the query plan depth and SQL parser recursion in Cube Store, the depth and number of stages of multi-stage calculations, and the depth of member references. It also adds a configurable data model compiler cache size.

Performance optimizations

Faster result streaming in the SQL API. Previously, the SQL API moved streamed rows from JavaScript to Rust one cell at a time. Now it moves them in columnar batches, the same transport that v1.7 introduced for the REST API. On a 10-million-row result, streaming is 1.47x to 1.76x faster, depending on the number of columns.

Cube Store performance toggles on by default. Most of the Cube Store performance options are now on by default, including CSV import job runners, group-by limits per partition, and batched metastore calls. The defaults of several repartitioning options changed too. To keep the previous behavior, set these options explicitly. This change first shipped in v1.7.31.

Compile state shared across tenants. In a multi-tenant deployment, now tenants with largely identical data models can share compiled state, which reduces the memory each tenant uses. Enable it with CUBEJS_COMPILER_MULTI_TENANT_SHARING.

This release also delivers:

  • Faster validation, metadata, and YAML transpilation for large data models.
  • Faster pre-aggregation partition range computation in the query orchestrator.
  • ClickHouse driver: up to 2.2x faster row streaming, faster result transformation, and no ping before each query.
  • DuckDB driver: about 2x faster row transformation.
  • Postgres driver: faster loading of user-defined types.
  • Cube Store: lower memory usage for queue results, and Cube Store results parsed without an extra copy.

Version changes

  • The Docker image now runs Node.js 24.21.0.
  • The native runtime that powers Python and Jinja data models supports Python 3.14.

What's next?

We're continuing to push more of the SQL API into the data source, and to make Cube's defaults harder to get wrong.

This release contains breaking changes. After checking the breaking changes above and their migration paths, please upgrade and give this release a try. As always, the changelog above reflects work contributed by members of the Cube community as well as the Cube team.

If you have questions or feedback, join our Slack community or open an issue on GitHub.

Enjoy the new features and happy Cube-ing!