Skip to content

pg_mooncake 0.3.0 · PostgreSQL 14–18 · DuckDB 2.0 & Apache Iceberg v2

Real-Time ColumnstoreBuilt for PostgreSQL

Create sub-second columnar mirrors of PostgreSQL tables powered by moonlink logical replication, pg_duckdb vectorized execution, and open Apache Iceberg v2 storage.

Forked from Mooncake Labs, now maintained by PGSTY · MIT & BSL-1.1 Exception

What’s new in pg_mooncake 0.3.0

Real-Time HTAP & Lakehouse Performance

Columnar analytics in Postgres without ETL pipelines

Combine PostgreSQL transactional writes with DuckDB 2.0 vectorized execution and open Apache Iceberg v2 object storage.

Up to 1000×Faster analytical scansVectorized DuckDB 2.0 scans over Parquet & Arrow vs regular Postgres heap tablesFaster analytical scans
< 10 msSub-second CDC syncLogical replication streams INSERT, UPDATE, and DELETE changes directly into Moonlink buffersSub-second CDC sync
Iceberg v2Open Lakehouse formatExport snapshots to S3, Cloudflare R2, or local disk for Spark, Snowflake, and PyIcebergOpen Lakehouse format
Zero ETLNo Kafka or DebeziumMirror local or remote PostgreSQL tables with a single CALL mooncake.create_table()No Kafka or Debezium

Core Engine Architecture

Write to rowstore, read from columnstore

pg_mooncake pairs an embedded Rust ingestion engine (moonlink) with DuckDB 2.0 vectorized execution via pg_duckdb and duckdb_mooncake.

01 / PG_MOONCAKE · COLUMNSTORE MIRROR

One command to mirror any Postgres table

◇ Native USING mooncake Table Access Method + Logical Replication

  • Creates a read-only USING mooncake mirror of any heap or partitioned table
  • Keeps your OLTP write path 100% unchanged—no triggers or dual writes
  • Can replicate from the local database or a remote PostgreSQL src_uri

Turn slow analytical queries into sub-second vectorized scans.

create_mirror.sql
-- Enable pg_mooncake (auto-loads pg_duckdb 1.2.0)
CREATE EXTENSION IF NOT EXISTS pg_mooncake CASCADE;
-- Create a real-time columnstore mirror of orders
CALL mooncake.create_table('orders_analytics', 'orders');
-- Write to rowstore, query from columnstore
INSERT INTO orders (customer_id, amount) VALUES (42, 199.95);
SELECT customer_id, SUM(amount) FROM orders_analytics
  GROUP BY customer_id;

02 / MOONLINK · REAL-TIME CDC ENGINE

Fast updates, deletes, and LSN consistency

◇ Embedded Rust background worker & standalone ingestion server

  • Buffers recent writes in memory as Apache Arrow record batches
  • Handles UPDATE and DELETE via Roaring Bitmap deletion vectors
  • Enforces PostgreSQL LSN barriers so queries always read consistent snapshots

Avoids the small-file problem of traditional Parquet/Iceberg writers.

moonlink_status.sql
-- Inspect active columnstore mirrors and WAL LSNs
SELECT * FROM mooncake.list_tables();
-- Returns: table, commit_lsn, flush_lsn, iceberg_warehouse_location
-- Force-flush buffered Arrow data into Parquet + Iceberg
CALL mooncake.create_snapshot('orders_analytics');
-- Compact Parquet files and rewrite deletion vectors
CALL mooncake.optimize_table('orders_analytics', 'full');

03 / DUCKDB_MOONCAKE · VECTORIZED SCAN

Powered by DuckDB 2.0 & pg_duckdb 1.2

◇ Multi-file Parquet statistics pruning + zero-copy Arrow scan

  • Merges flushed Parquet files and in-memory Arrow buffers on the fly
  • Uses DuckDB 2.0 multi-file Parquet statistics for segment elimination
  • Seamlessly joins columnstore tables with regular PostgreSQL heap tables

Full DuckDB analytical speed using standard PostgreSQL connections.

hybrid_join.sql
-- Join regular Postgres heap table with columnstore mirror
SELECT u.region, date_trunc('day', o.created_at) AS day,
       COUNT(*) AS orders, SUM(o.amount) AS revenue
FROM users u
JOIN orders_analytics o ON u.id = o.customer_id
WHERE o.created_at >= NOW() - INTERVAL '30 days'
GROUP BY u.region, day ORDER BY day DESC;

04 / APACHE ICEBERG v2 · ZERO-ETL LAKEHOUSE

Export to S3 / R2 & query your data lake

◇ Open Iceberg v2 metadata + external Parquet/Delta/Iceberg scans

  • Writes standard Apache Iceberg v2 metadata to local disk, S3, or R2
  • Query external Parquet, CSV, Iceberg, and Delta Lake files inside Postgres
  • Partition-archiving pattern: drop old Postgres partitions, keep full history in S3

Bridge operational Postgres and your cloud lakehouse without external pipelines.

iceberg_lakehouse.sql
-- Configure S3 / R2 credentials and default bucket
INSERT INTO duckdb.secrets (name, type, key_id, secret, region, scope)
  VALUES ('s3_lake', 'S3', 'AKIA...', 'secret...', 'us-east-1', 's3://my-bucket');
SET mooncake.default_bucket = 's3://my-bucket/warehouse';
-- Materialize a new Iceberg v2 snapshot on S3
CALL mooncake.create_snapshot('orders_analytics');

Documentation Sections

Explore the complete Mooncake documentation

Unified documentation for pg_mooncake v0.3.0, Moonlink v0.0.1, duckdb_mooncake v0.0.2, use-case architectures, and the legacy v0.1 Delta Lake archive.

Core Architecture · v0.3.0

Introduction & Architecture

Understand how pg_mooncake, Moonlink, duckdb_mooncake, and pg_duckdb 1.2.0 work together, and how v0.2/v0.3 evolved from v0.1.

Introduction & Architecture

Install · Hello World · Limits

Getting Started

Install pg_mooncake via Pigsty packages or build from source on PostgreSQL 14–18, run the Hello World tutorial, and review known limitations.

Getting Started

Procedures · Queries · Iceberg

SQL & Config Reference

Complete reference for mooncake.create_table, create_snapshot, optimize_table, list_tables, query shapes, Iceberg S3/R2 setup, and data lake scans.

SQL & Config Reference

HTAP · Archiving · Lakehouse · Logs

Use Cases & Patterns

Architectural blueprints for real-time operational analytics, time-partitioned table archiving, zero-ETL Postgres lakehouse, and OpenTelemetry logs.

Use Cases & Patterns

Legacy Reference Manual

v0.1 Archive (Delta Lake)

Complete historical reference for pg_mooncake v0.1, which used direct USING columnstore DDL and Delta Lake storage before the Moonlink redesign.

v0.1 Archive (Delta Lake)

MIT · BSL-1.1 Exception · Audit

About, License & SBOM

PGSTY community stewardship, MIT and BSL-1.1 linking exception licensing, Wayback Machine recovery provenance, and Cargo security audit reports.

About, License & SBOM

Quick Start

Run pg_mooncake in three steps

Install native packages via Pigsty, preload the extensions, and create your first real-time columnstore mirror.

  1. Install packages

    Install pg_duckdb and pg_mooncake with the pig package manager across 16 Linux targets and PostgreSQL 14–18.

    pig repo add pgsql -u && pig install pg_duckdb pg_mooncake
  2. Enable extension

    Set wal_level = logical and shared_preload_libraries = 'pg_duckdb,pg_mooncake', then enable pg_mooncake.

    psql -d postgres -c "CREATE EXTENSION IF NOT EXISTS pg_mooncake CASCADE;"
  3. Mirror & query

    Create a real-time columnstore mirror of your table with mooncake.create_table and run vectorized queries.

    psql -d postgres -c "CALL mooncake.create_table('orders_analytics', 'orders');"

Frequently Asked Questions

Understanding Mooncake & PGSTY Stewardship

Why is the PGSTY community maintaining pg_mooncake, duckdb_mooncake, and moonlink?

Mooncake Labs Inc., the creators of pg_mooncake, duckdb_mooncake, and moonlink, was acquired by Databricks, after which the original documentation site (docs.mooncake.dev) went offline and upstream maintenance paused. The PGSTY community recovered the complete historical documentation from the Internet Archive Wayback Machine and maintains the open-source forks—pgsty/pg_mooncake, pgsty/duckdb_mooncake, and pgsty/moonlink—for the PostgreSQL ecosystem.

What changed in PGSTY’s pg_mooncake 0.3.0 release?

pg_mooncake 0.3.0 upgrades the Rust PostgreSQL extension to pgrx 0.19.3 (supporting PostgreSQL 14–18), ports duckdb_mooncake (v0.0.2) to pg_duckdb 1.2.0 and DuckDB v2.0.0 (using exported multi-file Parquet statistics interfaces without object-cache lock reentrancy), fixes moonlink (v0.0.1) create_snapshot(lsn) hangs when unrelated tables advance database WAL, automatically sets REPLICA IDENTITY FULL on existing leaf partitions, and patches 20+ RustSec dependency advisories.

How does pg_mooncake v0.2 / v0.3 differ from v0.1?

In v0.1, users wrote directly to CREATE TABLE ... USING columnstore tables backed by Delta Lake, which struggled with small frequent OLTP inserts and updates. Starting in v0.2 and v0.3.0, pg_mooncake uses a columnstore mirror architecture powered by moonlink: your application continues writing to standard PostgreSQL heap tables (INSERT/UPDATE/DELETE), while moonlink streams changes via logical replication into in-memory Arrow buffers, Roaring deletion vectors, and Apache Iceberg v2 Parquet files. See v0.1 vs v0.2 & v0.3.

What licenses apply to pg_mooncake, duckdb_mooncake, and moonlink?

pg_mooncake and duckdb_mooncake (along with moonlink_rpc, moonlink_proto, moonlink_error, and moonlink_table_metadata) are licensed under the permissive MIT License. The core moonlink engine is licensed under BSL-1.1 (converting automatically to Apache-2.0 on May 5, 2029) with an explicit PG_MOONCAKE LINKING & DISTRIBUTION EXCEPTION that permits unrestricted linking, copying, modification, and redistribution when embedded in or distributed as part of pg_mooncake. See License Details.

Why did my mooncake.create_table call fail when passing source_uri?

Upstream v0.2 documentation contained a parameter typo (source_uri => ...). The actual SQL procedure signature in pg_mooncake is mooncake.create_table(dst text, src text, src_uri text DEFAULT NULL, table_config json DEFAULT NULL). Always pass src_uri when replicating from a remote PostgreSQL URI. See Create Columnstore Table.

What is PGSTY’s maintenance scope and security reporting policy?

PGSTY maintains supply-chain continuity, PostgreSQL 14–18 and pg_duckdb compatibility, and Linux RPM/DEB packaging across 16 OS/arch targets, with full dependency disclosures in the SBOM. We do not commit to developing new upstream features—roadmap items are handled on a best-effort basis—but security vulnerabilities and critical bug reports are always welcome via GitHub Issues.

Ready to run real-time columnar analytics in PostgreSQL?Follow the Getting Started guide, explore the SQL reference, or read the v0.3.0 release notes.