PostgreSQL 17.2 · Measured, not guessed

Your PostgreSQL, minus the slow reports that should never exist.

MontuDB is a PostgreSQL 17.2 fork whose optimizer measures the real cardinality of your data combinations instead of guessing it. When a reporting segment is effectively empty, it skips the multi-million-row scan — and returns the exact same result in milliseconds.

The root cause

PostgreSQL guesses your data is independent. It almost never is.

Before running a query, every database estimates how many rows each step produces. PostgreSQL assumes column independence: that two filters applied together behave as if unrelated. In a real data warehouse they're correlated — enterprise vendors sell only electronics, smb vendors sell only grocery. Ask for "enterprise × grocery" and that segment is genuinely empty. PostgreSQL doesn't know that. It multiplies selectivities, assumes plenty of rows, and scans an entire 22-million-row fact table only to return zero rows.

PostgreSQL 17.2
HashAggregate est. 1.2M
Seq Scan order_items 22,000,000
Hash Join · products ⋈ vendors
Execution Time ≈18,211 ms
22M rows scanned → result: 0 rows. Pure waste.
MontuDB 2.30
Measured intersection = EMPTY
Empty-first plan engaged
Execution Time ≈21.4 ms
Fact table never touched → same result: 0 rows.
The mechanism · RealCost

It measures the combination instead of multiplying probabilities.

The core of the Montu optimizer is measured-cardinality probing. During planning of a hinted query, it probes the real post-filter intersection of joined dimensions — and when that intersection is provably empty, it forces an empty-first plan so the giant fact table is never executed.

01

Identify join pairs

Finds dimension pairs and trios directly connected by a join edge — e.g. vendors ⋈ products.

02

Probe the reality

Measures the real intersection after WHERE filters are applied, instead of multiplying selectivities the way PostgreSQL does.

03

Detect the empty

If the post-filter intersection is provably empty with full coverage, it records an empty-intersection cascade.

04

Resolve empty-first

The empty branch is resolved first under a controlled planning budget, so the fact table is never run.

Join-connectivity guard

Montu only probes pairs joined by a real edge. It never executes a cartesian probe — which would be ruinously expensive.

Sample-coverage guard

It applies the correction only when the measurement has enough coverage to be trustworthy.

Fail-closed

In any ambiguous situation, Montu disengages and returns PostgreSQL's standard plan. That's why it never makes the result worse.

opt-in — activate Montu on a single query
SELECT /*+ montu_optimizer(5) */
       region, sum(amount)
FROM   order_items oi
JOIN   products p ON p.id = oi.product_id
JOIN   vendors  v ON v.id = p.vendor_id
WHERE  v.vendor_tier = 'enterprise' AND p.category = 'grocery'
GROUP BY region;
-- Without the hint, behaviour is pure PostgreSQL 17.2, byte for byte.
Benchmarks · auditable

Real numbers, with the definition attached.

Metric rule (applies to every table): every "Nx faster" is PostgreSQL Execution Time ÷ MontuDB Execution Time, reading only the Execution Time: line of EXPLAIN (ANALYZE, BUFFERS). Planning time, Montu's probe time and wall-clock are reported in separate columns — they are never folded into the headline number. Results are always identical (same rows).

Environment: MontuDB (PostgreSQL 17 fork), Raspberry Pi 5. Synthetic warehouse mktg_db (~9.2 GB): order_items 22M, campaign_events 28M; customers 3.5M, products 50k, vendors 2k. Single-thread (max_parallel_workers_per_gather=0), fresh basic stats, useful indexes present. The empty: vendor_tier × category are perfectly anti-correlated, so "enterprise × grocery" is genuinely empty. Medians of 5 runs.

Query Business report PG exec Montu exec Speedup (exec) Montu probe Same result
QV22_01Grocery revenue by region18,211 ms21.4 ms850×14.2 s
QV22_10Grocery revenue by customer status17,912 ms21.3 ms841×12.9 s
QV22_05Grocery revenue by country17,856 ms21.4 ms835×13.3 s
QV22_16Grocery units / top line by region17,744 ms21.5 ms825×14.2 s
QV22_03Distinct grocery customers by region17,677 ms21.6 ms820×14.1 s
QV22_02Grocery units / lines by year14,298 ms21.3 ms670×12.8 s
QV22_17Grocery revenue + avg ticket by country3,728 ms21.3 ms175×12.9 s
QV22_15Grocery revenue by region and year3,451 ms21.4 ms162×14.4 s
Tier 3 — single-run peaks with probe over budget (footnote, never a headline)

⚠ These are single-run points where Montu's probe (~69 s) overruns the budget and PG's execution. Shown for completeness only.

QueryBusiness reportPG execMontu execSpeedup (exec)Montu probe
QV22_07smb-electronics units by region59,178 ms24.4 ms2425×~69 s
QV22_08smb-electronics lines by year32,520 ms21.5 ms1516×~69 s
QV22_09smb-electronics customers by region5,320 ms28.0 ms190×~68 s

172 varied queries (the "100Q" report suite plus an out-of-sample suite with CTEs, subqueries, unions, aggregations). This battery exists to prove the gain comes with no hidden regressions.

172
Queries
21
Improved
151
Neutral
0
Regressions
Query PG exec Montu exec Saved Speedup Same result
q029122.636 ms1.732 ms120.9 ms70.81×
q02789.047 ms1.792 ms87.3 ms49.69×
q02484.149 ms1.726 ms82.4 ms48.75×
q03363.424 ms24.580 ms38.8 ms2.58×
q03961.326 ms24.313 ms37.0 ms2.52×
q03459.549 ms24.380 ms35.2 ms2.44×
q03859.646 ms24.485 ms35.2 ms2.44×
q01918.651 ms12.666 ms6.0 ms1.47×

Across 172 queries MontuDB improved 21 and hurt none, always returning identical results. Largest speedup 70.81× (q029); 172/172 results byte-identical. Where PostgreSQL is already good, MontuDB is neutral.

Why it's safe to adopt

Additive. Isolated. Opt-in.

Measured cardinality, not guessed

Montu probes the real intersection of your dimensions during planning. Where PostgreSQL multiplies selectivities and misses, Montu measures and hits.

Safe by default

Opt-in: without the hint, behaviour is byte-for-byte PostgreSQL 17.2. On any doubt, Montu disengages and returns the standard plan. It never makes results worse.

Drop-in PostgreSQL

Same protocol, same tools, same backups. Installs side-by-side under /opt/montudb, without replacing your existing PostgreSQL or its psql.

Editions

The optimizer core is Community and free.

Enterprise adds evolving RealCost cache and cost-governance features on top.

Feature Community Enterprise
RealCost optimizer (measured cardinality + empty-first plan)
Auditable RealCost EXPLAIN
Per-query RealCost cache (fail-closed, safe) (basic)
Evolving RealCost cache
Measured-cost extraction & injection
Drift-validation policies (STRICT / DRIFT_PCT / TRUST)always STRICT

The features above are real. Commercial terms (pricing, limits) for Enterprise are being finalized — talk to us before deploying the editions table publicly.

Download · MontuDB 4.8

Installs in minutes, alongside your PostgreSQL.

Based on PostgreSQL 17.2 · distributed under the PostgreSQL License · reports as PostgreSQL 17.2 (MontuDB 4.8). Production builds (optimized -O2, assertions off, stripped).

Coexists, never replaces

Installs under /opt/montudb/4.80. Doesn't touch the system psql or the postgresql service.

Files only

It does not initialize or start a cluster automatically. You run initdb / pg_ctl yourself.

Suggested port 55432

So it never clashes with a PostgreSQL on 5432.

Raspberry Pi 64-bit

Uses the arm64 artifacts. amd64 and arm64 are both first-class.

Platform Format Size SHA-256
Debian / Ubuntu / RPi OS 64-bit arm64 deb 4.7 MB
ba4f5d5c…65476fe8
.deb
Debian / Ubuntu amd64 deb 5.2 MB
ba3ff885…9f54270b
.deb
RHEL / Rocky / Alma / Oracle Linux x86_64 rpm 5.6 MB
b5374f27…09145f2a
.rpm
RHEL / Rocky / Alma / Oracle Linux aarch64 rpm 5.5 MB
60698f0c…1d067fce
.rpm
Portable tarball amd64 tar.gz 8.1 MB
789b8425…fb2e4f62
tar.gz
Portable tarball arm64 tar.gz 7.9 MB
36ebbff8…8b15049c
tar.gz
Docker image amd64 docker 52 MB
7ea79862…7d332eef
.tar
Docker image arm64 docker 52 MB
7e45bb49…b93a1ff0
.tar

Verify integrity: SHA256SUMS · release-manifest.json. On Linux: sha256sum -c SHA256SUMS.

Install (Debian / Ubuntu / RPi OS · arm64)
# .deb
sudo dpkg -i montudb_4.80-1_arm64.deb

# RHEL / Rocky / Alma (x86_64)
sudo rpm -i montudb-4.80-1.x86_64.rpm

# Docker
docker load -i montudb-4.80-docker-arm64.tar
First run (manual · suggested port 55432)
/opt/montudb/4.80/bin/initdb -D /path/to/data
/opt/montudb/4.80/bin/pg_ctl -D /path/to/data \
   -o "-p 55432" -l log.txt start
/opt/montudb/4.80/bin/psql -p 55432 -c "SELECT version();"
# -> PostgreSQL 17.2 (MontuDB 4.8) ...

Documentation: Manual (PDF) · README · Release notes.

Methodology · honesty contract

Exactly what the number means — and what it doesn't.

MontuDB's numbers are real and audited, but only true inside a precise definition. Speedup = Execution Time only — PostgreSQL's Execution Time ÷ MontuDB's, from EXPLAIN (ANALYZE, BUFFERS). Results are identical (verified by row identity / md5). The winning reports return an empty result (0 rows) — a real emptiness between dimensions. Fresh basic stats; no pg_statistic edits, no n_distinct tricks.

Claims we stand behind

  • Up to N× faster in Execution Time on selected report joins, with fresh basic stats and useful indexes — identical results.
  • Turns a multi-million-row fact-table scan into an empty-first plan when a report segment is structurally empty.
  • Where PostgreSQL is already fast, MontuDB is neutral.
  • 172 queries, 0 regressions, 21 improvements, identical results.

What we never claim

  • "Always faster"
  • "Replaces the PostgreSQL optimizer"
  • "From 5 minutes to milliseconds"
  • "Includes planning time" (the speedup does not)
  • "Speeds up every query"
  • Any number without the "Execution Time" label nearby

The fixture is synthetic and single-thread: the emptiness is constructed (perfectly anti-correlated tiers). The mechanism is real; the magnitudes are fixture-specific. The 2425× point is a single run with probe overrun — footnote, never a headline.