Delta Classic - DuckDB Extension
February 21, 2026 · View on GitHub
A minimal DuckDB extension that lets you attach a directory of Delta tables as a single database. Works with any filesystem DuckDB supports: local, S3, ABFSS, GCS.
Installation
Requires DuckDB v1.4.4 or later. Fabric notebook uses an old version (1.2.2), so you need to upgrade
!pip install duckdb --upgrade
notebookutils.session.restartPython()
import duckdb
conn = duckdb.connect()
conn.sql("install delta_classic FROM community ")
conn.sql(f"""
ATTACH 'abfss://{ws}@onelake.dfs.fabric.microsoft.com/{lh}.Lakehouse/Tables/{schema}'
AS db (TYPE delta_classic, PIN_SNAPSHOT);
USE db;
""")
The Problem
Today, if you have a directory with multiple Delta tables, you need to attach each one individually:
for tbl in tpch_tables:
conn.sql(f"ATTACH '{base_path}/{tbl}' AS {tbl} (TYPE DELTA, PIN_SNAPSHOT)")
This creates a separate database per table. Annoying.
How It Works
This extension does the absolute minimum:
- Lists subdirectories at the given path
- Checks which ones have a
_delta_logfolder (i.e., are actual Delta tables) - Internally calls
ATTACH ... (TYPE DELTA, PIN_SNAPSHOT)for each table when you first query it - Exposes them all through a single virtual catalog
There is zero reimplementation of Delta reading — everything delegates to the existing Delta extension.
Schema Discovery
The extension auto-detects the directory structure:
Multi-schema — when the path contains subdirectories of tables:
Tables/
├── CH0030/ → schema "CH0030"
│ ├── orders/ → table (has _delta_log)
│ └── customers/ → table (has _delta_log)
└── CH0060/ → schema "CH0060"
└── orders/ → table
ATTACH '.../Tables' AS db (TYPE delta_classic);
SELECT * FROM db.CH0030.orders;
Single-schema — when the path directly contains Delta tables:
CH0030/
├── orders/_delta_log/
└── customers/_delta_log/
ATTACH '.../CH0030' AS db (TYPE delta_classic);
SELECT * FROM db.CH0030.orders;
Works with any path DuckDB supports: local, S3, ABFSS, GCS.
Why "Classic"?
The name is a tongue-in-cheek reference to what Delta has become. Delta Lake started as a beautifully simple idea — Parquet files plus a transaction log on storage. But with catalog-managed commits, Unity Catalog has taken over as the transaction coordinator itself. Commits are no longer just appended to _delta_log by the compute engine — they're validated, tracked, and ordered server-side by UC. The transaction log on disk is no longer the source of truth. Delta, in practice, has become a catalog-managed table format.
To be fair, catalog-managed commits aren't a bad thing — they're essential for complex scenarios like multiple concurrent writers, multi-table transactions, and centralized governance at scale. If you need that, you need that.
But many workloads are simpler: read-heavy analytics, single-writer pipelines, local exploration. For those, a catalog server is overhead you don't need. Delta Classic is a nod to that original idea: your tables are just directories with a _delta_log, and that log is the truth. No catalog service coordinating your commits. Just files on storage, the way Delta started.
Why Storage-Based Delta Management?
Using plain storage (directories of Delta tables) instead of a metastore like Unity Catalog has real advantages:
- No catalog dependency — you don't need Unity Catalog, Hive Metastore, or any external service to organize your tables
- Works everywhere — local filesystem, S3, ABFSS, GCS. Just point at a directory
- Simple and portable — your data layout is your catalog. Copy a folder, and you've copied a database
This extension just makes that pattern first-class in DuckDB.
Why an Extension?
Honestly, AI is becoming good enough to generate full extension out of thin air
Requires DuckDB v1.4.4 or later.