Cube Core version 1.6 is the latest release to date.

The flagship feature of this release is the new, substantially upgraded and improved Cube Store, enabling the use of pre-aggregations for multi-stage calculations powered by Tesseract, Cube's next-generation data modeling engine.

This release contains breaking changes. Cube Store upgrade as well as strict validation of join paths in views and strict access policy matching are breaking changes. Please read respective sections carefully.

Other notable changes include support for precise decimals in Cube Store and general availability of query pushdown in the SQL API.

As always, we recommend testing the new version on a staging environment before deploying it to production.

BREAKING: Cube Store upgrade

Cube Store is Cube's specialized, high-performance, columnar data store designed to accelerate query performance by leveraging pre-aggregations. It makes use of well-established open-source technologies such as Apache Parquet file format, Apache Arrow memory format, and Apache DataFusion query engine.

With this release, we're completing a journey of upgrading Cube Store to DataFusion 46.0 from the previously used DataFusion 4.0 version with occasional cherry-picks. The reason for this upgrade is that DataFusion has evolved significantly, adding many new features and performance optimizations. For instance, this upgrade brings complete support for DECIMAL data type (fixed-point numbers with up to 38 digits) as well as query planning with common-table expressions (CTEs).

We can't emphasize enough how important the last bit is, as CTEs are widely used by Tesseract, the next-generation data modeling engine, to implement multi-stage calculations. The upgraded Cube Store unlocks accelerating multi-stage measures with pre-aggregations, which was not possible before.

Now, when querying the data model from the period-to-date calculations example, you can get and execute the following SQL query that uses pre-aggregations in Cube Store. Note multiple stages expressed as CTEs:

WITH time_series AS (
SELECT to_timestamp('2025-01-01T00:00:00.000') date_from, to_timestamp('2025-03-31T23:59:59.999') date_to UNION ALL
SELECT to_timestamp('2025-04-01T00:00:00.000') date_from, to_timestamp('2025-06-30T23:59:59.999') date_to UNION ALL
SELECT to_timestamp('2025-07-01T00:00:00.000') date_from, to_timestamp('2025-09-30T23:59:59.999') date_to UNION ALL
SELECT to_timestamp('2025-10-01T00:00:00.000') date_from, to_timestamp('2025-12-31T23:59:59.999') date_to
),
cte_1 AS (
SELECT
date_trunc('quarter', "prior_date__time_month") "prior_date__time_quarter",
sum("prior_date__revenue_ytd") "prior_date__revenue_ytd"
FROM prod_pre_aggregations.prior_date_main AS "prior_date__main"
WHERE (
CONVERT_TZ("prior_date__time_month", '+00:00') >= date_trunc('year',
( SELECT min("date_from") "value" FROM time_series )
)
AND CONVERT_TZ("prior_date__time_month", '+00:00') <= (
SELECT max("date_to") "value" FROM time_series
)
)
GROUP BY 1
ORDER BY 1 ASC
),
cte_2 AS (
SELECT
"time_series"."date_from" "prior_date__time_quarter",
sum("rolling_source"."prior_date__revenue_ytd") "prior_date__revenue_ytd"
FROM
time_series AS "time_series"
LEFT JOIN cte_1 AS "rolling_source" ON "rolling_source"."prior_date__time_quarter" >= date_trunc('year', "time_series"."date_from") AND "rolling_source"."prior_date__time_quarter" <= "time_series"."date_to"
GROUP BY 1
ORDER BY 1 ASC
)
SELECT
"fk_aggregate"."prior_date__time_quarter" "prior_date__time_quarter",
"fk_aggregate"."prior_date__revenue_ytd" "prior_date__revenue_ytd"
FROM (
SELECT * FROM cte_2 AS "cte_2"
) AS "fk_aggregate"
ORDER BY 1 ASC

Also, see the recipe for the internal rate of return (XIRR) calculations, accelerated with pre-aggregations in the upgraded Cube Store. Here's the generated SQL query for multi-stage XIRR calculation in Cube Store:

WITH cte_0 AS (
SELECT
date_trunc('day', "payments__date_day") "payments__date_day",
date_trunc('day', "payments__date_day") "payments__date_day",
sum("payments__total_payments") "payments__total_payments"
FROM prod_pre_aggregations.payments_main_xirr AS "payments__main_xirr"
GROUP BY 1, 2
ORDER BY 1 ASC, 2 ASC
),
cte_1 AS (
SELECT
"fk_aggregate"."payments__date_day" "payments__date_day",
XIRR(
"fk_aggregate"."payments__total_payments",
"fk_aggregate"."payments__date_day"
) "payments__xirr"
FROM (
SELECT * FROM cte_0 AS "cte_0"
) AS "fk_aggregate"
GROUP BY 1
ORDER BY 1 ASC
)
SELECT
"fk_aggregate"."payments__date_day" "payments__date_day",
"fk_aggregate"."payments__xirr" "payments__xirr"
FROM (
SELECT * FROM cte_1 AS "cte_1"
) AS "fk_aggregate"
ORDER BY 1 ASC

Using the upgraded Cube Store with Tesseract in the fashion shown above would require setting to true the following environment variables: CUBEJS_TESSERACT_SQL_PLANNER, CUBEJS_TESSERACT_PRE_AGGREGATIONS, CUBEJS_CUBESTORE_ROLLING_WINDOW_JOIN.

Upgrade considerations. Due to changes in the data types and storage format, the upgraded Cube Store builds pre-aggregation partitions that are not compatible with the previous Cube Store version. The upgraded Cube Store is able to read pre-aggregation partitions created by the previous Cube Store version, so only newly created partitions will use the new format. However, in some cases, the existing partitions might need to be rebuilt from scratch. Please keep this in mind when planning and executing the upgrade.

Upgrade considerations for Cube Cloud users. In Cube Cloud, all deployments will continue using the previous version of Cube Store while we're gradually rolling out the new Cube Store over the coming weeks. If you'd like to switch to the new Cube Store now, please contact the customer success team.

Please report any issues you encounter with the upgraded Cube Store on GitHub and in the Slack community. We're really looking forward to your feedback and we'll be helping to get the issues resolved.

Precise decimals in Cube Store

Previously, Cube Store only supported up to 16 digits of precision for decimal numbers, while the upgraded Cube Store in this release can now handle up to 38 digits of precision, aligning with the capabilities of many modern databases.

So, this release introduces a new environment variable, CUBEJS_DB_PRECISE_DECIMAL_IN_CUBESTORE (set to false by default), which controls how decimal columns are handled when exporting data from a data source to Cube Store. If this environment variable is turned on, when data is exported from a data source to Cube Store, decimal columns maintain their precision and scale specifications (e.g., DECIMAL(10, 2)) rather than being converted to a generic decimal type.

Upgrade considerations. Enabling precise decimals may require that existing pre-aggregation partitions are rebuilt from scratch. That is only going to happen if the columns in the underlying data source use decimal types with precision and scale specifications.

BREAKING: Strict validation of join paths

Join paths serve as a mechanism to remove the ambiguity of joins in the data model. When join paths are used in views, it's important to define them in a non-ambiguous manner to ensure that Cube can generate correct SQL queries.

Previously, Cube allowed to have the following set of join paths in the same view: orders.locations and orders.customers.locations. Allowed here means that Cube would not raise an error during the data model compilation. However, such definitions are not sound since Cube would only reference a single cube once in the generated SQL query, e.g., ... FROM orders LEFT JOIN customers ... LEFT JOIN locations ..., making it impossible to follow both join paths simultaneously. Ultimately, this can lead to getting incorrect query results without any indication of an issue.

To prevent this from happening, now we've introduced strict validation of join paths in views. Data model compilation will fail with the following error if ambiguous join paths are detected: Views can't define multiple join paths to the same cube. View 'order_info' has multiple paths to 'locations': 'orders.locations', 'orders.customers.locations'. Use extends to create a child cube and reference it instead.

Please see the test cases to learn more.

Upgrade considerations. If your data model contains unsound join paths in views, you will need to refactor it to eliminate the ambiguity. Currently, the recommended way to do so is by aliasing cubes such as location above through creating a child cube using the extends parameter. Then, you can reference the child cube in the join paths.

Going forward, we plan to support join aliases to eliminate the need for creating child cubes in such cases.

BREAKING: Strict access policy matching

Access policies serve as a way to define member-level and row-level access controls declaratively in the data model.

Previously, all access policies that match the request were combined together, independently for member-level and row-level policies. Subsequently, combining multiple access policies with different sets of members could lead to a counter-intuitive outcome, when policies would expand the row-level access for non-overlapping members.

Image

To reduce confusion when using access policies, we've updated the access policy matching to apply and combine only policies that include all members from the query. As the result, the row-level access would not expand in a counter-intuitive manner. However, it also means that if a query contains members that are not fully covered by any access policy, the query will return no data.

Image

See a few examples to learn more.

Upgrade considerations. Review your access policies to ensure that they fully cover the members used in queries. Consider comparing the query results before and after the upgrade (in a production and a staging environment) to identify any discrepancies.

IMPORTANT: General availability of query pushdown in the SQL API

With this release, query pushdown in the SQL API leaves the public preview and is now generally available. Since it was enabled by default in v1.0, it has proven to be a stable and important feature that significantly expands the capabilities of the SQL API.

DEPRECATED: Elasticsearch driver

The Elasticsearch driver is deprecated and will be removed in a future release.

Due to the non-relational nature of Elasticsearch, the driver has amassed a number of standing issues over time while still having very limited adoption as any production usage of it is hardly justified given known limitations.

New in configuration

New CUBEJS_DEFAULT_TIMEZONE environment variable

This new environment variable allows to specify the default time zone for queries, used when no timezone is specified in queries. By default, it is set to UTC. It can be useful for cases whem the majority of queries are expected to use a specific time zone, e.g., all your users are sharing the same time zone and you want to avoid specifying it in every query.

New in APIs and client libraries

Query timezone in /cubesql API endpoint

Similarly to the /load endpoint of the REST API, the /cubesql endpoint of the SQL API now supports the timezone parameter that allows to specify the time zone for a query. It can be useful for cases whem queries come from users located in different time zones.

lastRefreshTime in /cubesql API response

Now the /cubesql endpoint of the SQL API includes the lastRefreshTime field in its response. This field indicates the timestamp of the last cache refresh for the result set. This comes as a handy follow-up for the cache parameter support added in v1.5.0, allowing clients to specify cache control for queries.

baseRequestId in the JavaScript SDK

The new baseRequestId parameter was added to the methods of the JavaScript SDK. It allows to specify a base request ID (spanId) to be explicitly provided for the request. Might be useful when you'd like to use the same request ID across multiple requests for easier tracing and correlation. If not provided, a random request ID will be generated as before.

@cubejs-client/vue package discontinued

Version 2 of the Vue front-end framework has reached its End of Life (EOL). Consequently, the client library for this version of Vue has been deprecated and will not receive further updates. We highly recommend upgrading to @cubejs-client/vue3, supporting Vue 3.

New in data sources

New default renewal threshold for Firebolt

By default, Cube uses 2-minute refresh keys for all data warehouses. We've aligned Firebolt with others by setting its default refresh key to 2 minutes as well.

Perfomance optimizations

A lot of effort was put into further improving the performance of the data model compilation and reducing its memory footprint, especially in multi-tenant environments. On top of that, the API instance startup time was improved by lazy-loading vendor SDKs when needed, e.g., for AWS, GCP, Azure. Finally, the query planning performance in the SQL API has been significantly improved for cubes/views with many members.

What’s next?

We're looking forward to your feedback on the upgraded Cube Store and other features in this release! Please join our Slack community to share your thoughts and ask questions.

We're hoping to bring the next release soon, focusing on Tesseract.

Don't hesitate to try the new release in our managed cloud offering, which comes with a handy free plan.