Xeplr Pro Suite

Xeplr DW

When a source table outgrows live queries, copy it into a local DuckDB replica and build a cube over it — a pre-aggregated table at a grain you choose, profiled without scanning production and sized by an exact count before anyone is told it is worth building.

Partly built. Some of this is working and some of it is not. The limits below are current and specific — read them as part of the description, not as small print.

The report that takes four minutes

A table crosses some threshold and every query over it becomes slow. The usual answer is a warehouse project with its own team, its own tooling and its own year. For one slow table that is a very large hammer.

How it works

Two stages, on purpose

Replicating the source table into a local copy is expensive, network-bound and touches production, so it runs as a job. Building cubes from that copy touches nobody and costs seconds. The split is what keeps the builder interactive.

A verdict from a count, never the estimate

The design steps show no size figure. Review shows the estimate, and a verdict only once the rows have been counted for real over the local replica — which is cheap enough to do every time.

Profiled without scanning

Thirty exact COUNT(DISTINCT) on a 20M-row table is thirty full scans. The engine reads the database’s own catalog statistics instead, and falls back to a 100k-row sample only where the catalog leaves gaps. A sampled figure is shown as a floor, never as "about".

Averages are never stored

Ask for Avg(revenue) and the cube stores Sum and Count, dividing at read time. The average of three averages is not the average, so a stored one is wrong the moment the cube rolls up from days to months.

Distinct counts are stored, not added up

A distinct count is built and answers queries at exactly the cube’s grain. A customer active in two regions is one customer by month and two by month-and-region, so a coarser query refuses rather than adding it up.

One press to Build

Build refreshes the tables a cube reads that are past their own staleness tolerance, then rebuilds. A fresh table is skipped with a line saying why, and a finished copy rebuilds the cubes reading it with nobody pressing anything.

Joins happen only in DuckDB

Every table is copied as-is, so a cube can span several connections and the source is never asked to join. A table on the canvas with no join is refused, and LEFT is the default so a missing customer never drops an order.

A failed refresh keeps the old copy

A replica is upserted or replaced, never appended, and a replacement is staged and swapped in. Failed and stuck work shows on one list, so a copy that never finished is as visible as one that failed.

What it does not do yet

Current as of the product readme. If something here matters to you, ask — some of it is next.

  • ClickHouse is the intended store and is not implemented.
  • A distinct count cannot be rolled up to a coarser grain. A HyperLogLog sketch would make it addable; that lands with ClickHouse.
  • A cube serves one reporting timezone. A second timezone means a second cube.
  • Every replica in a warehouse shares one DuckDB file, which takes one writer at a time on one machine — loads queue behind each other.
  • The engine and builder do not run on their own. Storage, copies, builds and scheduling are provided by Xeplr BI.

See it against your own data

A demo runs on your schema, not a sample dataset. Thirty minutes, no deck.