docs: propose native DuckLake layered storage (SQLite-catalog) - #74
docs: propose native DuckLake layered storage (SQLite-catalog)#74db-tycoon-stephen wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a proposal for native DuckLake layered storage using a SQLite-catalog to enable a local-first lakehouse on object storage. The review feedback highlights a validation issue with the proposed dbt-duckdb profile configuration, which does not support custom fields like is_ducklake or options out-of-the-box, and identifies a missing markdown reference link for [no-legacy stance].
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
…d link - Clarify the attach syntax (is_ducklake/options) is native in dbt-duckdb >= 1.10 (validated on 1.10.1 in spike 4); older versions reject it and need a custom plugin. Implementation must pin a version floor. - Replace the undefined [no-legacy stance] markdown reference with plain text. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review triage — commit
|
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces a proposal for a native DuckLake layered storage architecture using a SQLite-backed catalog to enable multi-process, local-first lakehouses. The feedback identifies two key improvements in the proposal's examples: ensuring the SQL ATTACH statement uses READ_ONLY TRUE for better DuckDB version compatibility, and adding the missing data_path option to the raw attachment in the dbt profile configuration.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
A DuckLake catalog stores data_path in metadata at creation, so re-attaching an existing catalog (raw, created by ingestion) needs no data_path — only the catalog created here (mart) specifies it. Verified by re-attaching a ducklake:sqlite: catalog read-only with no data_path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request adds a new proposal document (docs/proposals/ducklake-layered-storage.md) outlining a native DuckLake layered storage architecture using a SQLite-catalog. The feedback points out that the dbt profile YAML example in the proposal is missing the required schema field, which would cause dbt validation to fail, and suggests adding a default schema to make the example valid.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
…view) The condensed profile example omitted schema:, which dbt requires (spike 4's working profile had it). Add schema: main to keep the example copy-pasteable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1e193b4 to
3640ee4
Compare
…d link - Clarify the attach syntax (is_ducklake/options) is native in dbt-duckdb >= 1.10 (validated on 1.10.1 in spike 4); older versions reject it and need a custom plugin. Implementation must pin a version floor. - Replace the undefined [no-legacy stance] markdown reference with plain text. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A DuckLake catalog stores data_path in metadata at creation, so re-attaching an existing catalog (raw, created by ingestion) needs no data_path — only the catalog created here (mart) specifies it. Verified by re-attaching a ducklake:sqlite: catalog read-only with no data_path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…view) The condensed profile example omitted schema:, which dbt requires (spike 4's working profile had it). Add schema: main to keep the example copy-pasteable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rebased onto main after six weeks. Three freshness fixes, no change to the design or the spike findings: - v0.1.10 shipped 2026-07-21, so stop describing it in the future tense. - Note that the ingestion rewrite's M6 (#87) now owns the DuckLake surface. The phasing here predates that milestone; M6 sets sequencing. - Drop the `project.py:141` line number (DatabaseConfig has since moved to :215) — the bare path can't rot again. Every code reference in "How it maps to the current code" was re-checked against main: ducklake_config.py is untouched since v0.1.0, DatabaseConfig still has the two fixed fields, attach_metadata_to_profiles still lives in scaffolding/observability_dbt.py, and analyze.md:68 still carries the error this proposal corrects. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Storage-engine proposal from a 4-spike investigation (all green): one DuckLake catalog per layer (SQLite metadata + Parquet, S3-able), composed via ATTACH; dbt reads raw read-only and materializes into mart. Key finding corrects docs/commands/data/analyze.md:68 — the read-while-ingest lock is a property of the catalog metadata backend (DuckDB-file locks per-process), not of DuckLake or SQLite. Real Rill 0.86 reads a ducklake:sqlite: catalog live during ingest with zero conflicts. Builds on the shipped layer-aware data model (#30), unblocks layer-granular backup (#31). Not part of v0.1.10. Filed #71, #72, #73. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…d link - Clarify the attach syntax (is_ducklake/options) is native in dbt-duckdb >= 1.10 (validated on 1.10.1 in spike 4); older versions reject it and need a custom plugin. Implementation must pin a version floor. - Replace the undefined [no-legacy stance] markdown reference with plain text. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A DuckLake catalog stores data_path in metadata at creation, so re-attaching an existing catalog (raw, created by ingestion) needs no data_path — only the catalog created here (mart) specifies it. Verified by re-attaching a ducklake:sqlite: catalog read-only with no data_path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…view) The condensed profile example omitted schema:, which dbt requires (spike 4's working profile had it). Add schema: main to keep the example copy-pasteable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rebased onto v0.1.12 after six weeks. Three freshness fixes, no change to the design or the spike findings: - v0.1.10 shipped 2026-07-21, so stop describing it in the future tense. - Note that the ingestion rewrite's M6 (#87) now owns the DuckLake surface. The phasing here predates that milestone; M6 sets sequencing. - Drop the `project.py:141` line number — DatabaseConfig has since moved (:215 on main, :212 on v0.1.12), so the bare path can't rot again. Every code reference in "How it maps to the current code" was re-checked against both branches: ducklake_config.py is untouched since v0.1.0, DatabaseConfig still has the two fixed fields, attach_metadata_to_profiles still lives in scaffolding/observability_dbt.py, and analyze.md:68 still carries the error this proposal corrects. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
3640ee4 to
babc6a4
Compare
What
Adds
docs/proposals/ducklake-layered-storage.md— a storage-engine proposal for giving each warehouse layer its own DuckLake catalog (SQLite metadata + Parquet, S3-able), composed viaATTACH; dbt readsrawread-only and materializes intomart.Docs-only, one new file.
Why
Came out of a 4-spike investigation (all green; DuckDB 1.5.3, ducklake
e6a3bd0a, real Rill 0.86, dbt-duckdb 1.10.1). Headline finding corrects shipped docs (docs/commands/data/analyze.md:68): the read-while-ingest lock that justified the Parquet bridge for Rill is a property of the catalog metadata backend (DuckDB-file locks per-process), not of DuckLake or SQLite. A SQLite-backed catalog supports live Rill reads during ingest — confirmed with the real Rill binary, 0 lock conflicts.Validated
ducklake:sqlite:catalog live during ingest, 0 conflicts.raw-catalog →mart-catalog viaprofiles.ymlattach:.Where this lands now
Drafted 2026-06-21, when v0.1.10 was still the security pass and DuckLake had no owner in the plan. Both have moved:
DuckLakeDestination,ObjectStorageDestination,tycoon attach ducklake.So this is no longer a standalone track competing for a slot. It's the design evidence feeding M6: the corrected lock model, the validated dbt profile shape, and the four spike results are what M6 would otherwise have to rediscover. The "Proposed phasing" section predates the milestone and its sequencing is M6's to set — the doc now says so.
Merging also fixes three dangling references. PTC-41, PTC-42, and PTC-43 all point readers at
docs/proposals/ducklake-layered-storage.mdfor the design and evidence, and that file exists only on this branch.Freshness re-check (2026-08-02)
Rebased onto
v0.1.12, the active release branch (CONTRIBUTING.md: feature and fix PRs target the release branch, notmain). This PR previously targetedmain; the rebase used--ontoso the four PTC-96 commits that are onmainbut not onv0.1.12don't ride along. Every code reference in "How it maps to the current code" was verified against both branches — none had rotted:mainandv0.1.12ingestion/ducklake_config.pymisnamedfilesystem/Parquet destinationDatabaseConfighas two fixed fields:215onmain,:212onv0.1.12), so the doc now cites the bare pathobservability_dbt.attach_metadata_to_profilesanalyze.md:68carries the wrong lock rationalemkdocs build --strictandruff==0.15.20(the versionv0.1.12pins in its dev group) both pass locally. The new page isn't inmkdocs.yml'snot_in_navlist, which is fine —ingestion-architecture.mdandproposals/v0.1.10-scope.mdaren't either, and unlisted pages are INFO-level, not a strict failure.Relationship
layers:block."ducklake_config.pyis misnamed).Open risk
data_path: s3://…is unproven (all spikes used local paths) — gated as Phase 1, and now a question for M6 rather than for this doc.Review status
Three rounds from Gemini Code Assist, all five threads resolved (dbt
attachfield validation, undefined link,READ_ONLY TRUE,rawdata_path, missingschema). No further bot review will arrive — Gemini was opted out repo-wide after this PR opened (#173).🤖 Generated with Claude Code