From f660ef918fc3e46fad7c179583359e61c747b940 Mon Sep 17 00:00:00 2001 From: Gabor Szarnyas Date: Thu, 23 Oct 2025 14:50:51 +0200 Subject: [PATCH 1/5] Add Frozen DuckLake blog post --- _posts/2025-10-24-frozen-ducklake.md | 369 ++++++++++++++++++ ...rozen-ducklake-creation-procedure-dark.svg | 39 ++ ...ozen-ducklake-creation-procedure-light.svg | 39 ++ .../frozen-ducklake-overview-dark.svg | 46 +++ .../frozen-ducklake-overview-light.svg | 46 +++ .../frozen-ducklake/github-filelist-url.png | Bin 0 -> 37547 bytes images/blog/thumbs/frozen-ducklake.png | Bin 0 -> 30482 bytes images/blog/thumbs/frozen-ducklake.svg | 23 ++ 8 files changed, 562 insertions(+) create mode 100644 _posts/2025-10-24-frozen-ducklake.md create mode 100644 images/blog/frozen-ducklake/frozen-ducklake-creation-procedure-dark.svg create mode 100644 images/blog/frozen-ducklake/frozen-ducklake-creation-procedure-light.svg create mode 100644 images/blog/frozen-ducklake/frozen-ducklake-overview-dark.svg create mode 100644 images/blog/frozen-ducklake/frozen-ducklake-overview-light.svg create mode 100644 images/blog/frozen-ducklake/github-filelist-url.png create mode 100644 images/blog/thumbs/frozen-ducklake.png create mode 100644 images/blog/thumbs/frozen-ducklake.svg diff --git a/_posts/2025-10-24-frozen-ducklake.md b/_posts/2025-10-24-frozen-ducklake.md new file mode 100644 index 00000000..074359bf --- /dev/null +++ b/_posts/2025-10-24-frozen-ducklake.md @@ -0,0 +1,369 @@ +--- +layout: post +title: "Frozen DuckLakes for Multi-User, Serverless Data Access" +author: "Mark Harrison (Madhive Data Engineering)" +thumb: "/images/blog/thumbs/frozen-ducklake.svg" +image: "/images/blog/thumbs/frozen-ducklake.png" +excerpt: "We show how you can build high-performance data lakes with no moving parts." +--- + +> This is a guest blog post by [Mark Harrison](https://www.linkedin.com/in/marhar) ([Madhive](https://www.madhive.com) Data Engineering). + +[DuckLakes](https://ducklake.select/) typically consist of two components: the catalog database and the storage. Obviously, there is no way around having some sort of storage to represent the data. But can we host a DuckLake without setting up a catalog database? In this blog post, we'll show how you can create a read-only cloud-based DuckLake without a database server. We call this a **“Frozen DuckLake”** because it is read-only and has no moving parts other than a cloud storage system. Maybe you do want to [build a snowman](https://www.youtube.com/watch?v=TeQ_TTyLGMs), too! + +Frozen DuckLakes have several advantages: + +* They have almost zero cost overhead on top of the storage of the Parquet data files. +* A Frozen DuckLake can be used for public-facing data (e.g., public buckets), since there are no extra services required over cloud or HTTP file access. +* They make the data immediately accessible in a SQL database with no special provisions required. +* They allow data files to live in different cloud environments, while being referenced from the same Frozen DuckLake. + +And, best of all, while a “Frozen DuckLake” is indeed frozen in time, the data can still be updated by creating a _new_ Frozen DuckLake – older versions can be accessed by retaining revisions of the DuckDB database file that encodes its catalog. + +## Designing Frozen DuckLakes + +### Setup and Requirements + +When we started looking at using DuckLake for storing some archival data, our setup looked as follows: + +* The data was read-only and stored in cloud buckets. +* We had a multi-reader, single-writer model, where one process would periodically update the archive. + +We had three requirements that we wanted to meet: + +* An external program was creating the Parquet files – we didn't want to disrupt that workflow. +* We didn't want to support, pay for, or operate a cloud database server in order to have an archive. +* We did not want to block a traditional multi-user DuckLake running in parallel with our read-only archival copy. + +### Design + +First, our workflow continues to store Parquet files organized into buckets on our cloud storage system. This is a write-once system – once Parquet files have been written, they are neither modified nor moved. + +Second, we periodically snapshot the state of these Parquet files into a DuckLake. Using the `ducklake_add_data_files()` function allows us to quickly ingest all the data in one Parquet file. This is a fast, read-only operation, since DuckLake only needs to read the Parquet metadata. We do this on a single computer, writing to a local DuckDB-formatted DuckLake file. All data references are to the Parquet files in the cloud buckets. This gives us a working single-user DuckLake, resident on a single machine. We then “publish” the DuckLake file by copying it to cloud storage. Once it has been published, the DuckLake can be accessed in read-only mode by any client that can access the cloud storage. + +We call the snapshotting and publishing steps **“freezing a DuckLake”**. In the rest of this post, we'll show a live demo on GitHub, then go into the details of creating and deploying Frozen DuckLakes using object storage (AWS S3 or compatible) and HTTPS. + +![Frozen DuckLake overview]({% link images/blog/frozen-ducklake/frozen-ducklake-overview-light.svg %}){: .lightmode-img } +![Frozen DuckLake overview]({% link images/blog/frozen-ducklake/frozen-ducklake-overview-dark.svg %}){: .darkmode-img } + +## Live Demo + +Here's a small database of space missions that lives on GitHub. You can access this database with this command and try the following queries yourself. + +```batch +duckdb ducklake:https://github.com/marhar/frozen/raw/refs/heads/main/space.ducklake +``` + +```sql +SHOW TABLES; +``` + +```text +┌──────────────┐ +│ name │ +│ varchar │ +├──────────────┤ +│ astronauts │ +│ mission_crew │ +│ missions │ +│ spacecraft │ +└──────────────┘ +``` + +We can list the space missions with the most countries represented like so: + +```sql +SELECT + m.name as mission, + count(DISTINCT a.nationality) AS nationalities, + string_agg(DISTINCT a.nationality, ', ') AS countries_represented +FROM missions m +JOIN mission_crew mc ON m.mission_id = mc.mission_id +JOIN astronauts a ON mc.astronaut_id = a.astronaut_id +WHERE mc.primary_crew = true +GROUP BY m.mission_id, m.name +HAVING count(DISTINCT a.nationality) > 1 +ORDER BY nationalities DESC +LIMIT 4; +``` + +```text +┌─────────────────────────────┬──────────────┬────────────────────────────────────────────────┐ +│ mission │ nationalities│ countries_represented │ +│ varchar │ int64 │ varchar │ +├─────────────────────────────┼──────────────┼────────────────────────────────────────────────┤ +│ International Space Station │ 7 │ Italy, UK, Denmark, USA, France, Japan, Russia │ +│ SpaceX Crew-5 │ 5 │ Denmark, Italy, Germany, Japan, USA │ +│ SpaceX Crew-7 │ 4 │ Denmark, Italy, USA, France │ +│ SpaceX Crew-6 │ 4 │ Denmark, Japan, Italy, France │ +└─────────────────────────────┴──────────────┴────────────────────────────────────────────────┘ +``` + +This query was served from a Frozen DuckLake, using only storage. + +## Creating and Freezing a DuckLake + +There are four steps required to create and freeze a DuckLake: + +1. Collect the list of data files to include in the DuckLake. +2. Generate a DuckLake creation script. The script must take care of the table creation and the data population. +3. Create the local DuckLake. +4. Publish the DuckLake. + +Visually, the process looks as follows: + +![Procedure of creating a frozen DuckLake]({% link images/blog/frozen-ducklake/frozen-ducklake-creation-procedure-light.svg %}){: .lightmode-img } +![Procedure of creating a frozen DuckLake]({% link images/blog/frozen-ducklake/frozen-ducklake-creation-procedure-dark.svg %}){: .darkmode-img } + +We will go into detail on each of these steps below. Complete scripts are available in the [`marhar/duckdb_tools` GitHub repository](https://github.com/marhar/duckdb_tools/tree/main/frozen-ducklake). + +### Collecting the List of Data Files + +In a typical Frozen DuckLake scenario, there is another program which is already creating the Parquet files that are going to be frozen and published. It could be a periodic archival system, an ML data system that is collecting and organizing training data, or even another live DuckLake. The key requirements of the data generating system are: + +* They must generate Parquet files and put them in some accessible storage system. +* The table name related to each file can be derived from the path or filename. For example, `stations.2025-01.parquet` might be the dump of station information for January 2025\. (Of course, if you have appropriate metadata from the generating system, you could use that as well. For example, there might be metadata relating the file `6235b4d2611184.parquet` to the stations table.) + +> **Multi-site Frozen DuckLakes.** A Frozen DuckLake is not limited to referencing data files in a single repository or data store. File references to multiple sites can be added when creating the DuckLake file. This might be an effective way to integrate two independent systems that are operating in different environments. + +If we are using cloud storage directly supported by DuckDB such as S3 or GCS, the task is made very simple using DuckDB's built-in [recursive file globbing](https://duckdb.org/docs/stable/data/multiple_files/overview.html#multi-file-reads-and-globs): + +```sql +COPY ( + SELECT file AS full_path + FROM glob('s3://mybucket/mypath/**/*.parquet') +) TO 'tmp_files.csv'; +``` + +If we are building a list of data files which are stored on GitHub, we will have to use the GitHub API to query and traverse the GitHub repository, using logic like this in [`github-filelist.sh`](https://github.com/marhar/duckdb_tools/blob/main/frozen-ducklake/bin/github-filelist.sh): + +```bash +pprocess() { + CPATH=https://api.github.com/repos/$REPO/contents/$DPATH + curl -s $CPATH > $TMPJ + + # print Parquet files, then recurse into all subdirs + duckdb -noheader -ascii -c " + SELECT download_url FROM '$TMPJ' + WHERE type='file' AND name LIKE '%.parquet' + ORDER BY name;" + for DPATH in $(duckdb -noheader -ascii -c " + SELECT path FROM '$TMPJ' WHERE type='dir' + ORDER BY name;"); do + process $REPO $DPATH + done +} +echo full_path > tmp_files.csv +process $REPO $DPATH >> tmp_files.csv +``` + +Full code for both of these methods is in the repository mentioned above, as [`cloud-filelist.sh`](https://github.com/marhar/duckdb_tools/blob/main/frozen-ducklake/bin/cloud-filelist.sh) and [`github-filelist.sh`](https://github.com/marhar/duckdb_tools/blob/main/frozen-ducklake/bin/github-filelist.sh). If you need to implement a custom file lister, one of these might be a good model. + +If the storage location is on GitHub (such as in our demo), we would run a command like this. Note the extra `"/tree/main/"` in the path: + +```batch +./github-filelist.sh https://github.com/marhar/frozen/tree/main/space +``` + +![The URL used by github-filelist.sh]({% link images/blog/frozen-ducklake/github-filelist-url.png %}) + +On a cloud provider, we would run something like this. + +```batch +./cloud-filelist.sh s3://mybucket/myfolder +``` + +In any case, the output of these programs is the same: a CSV file with a single field, the full path of the data file, which will act as the input to the next step. + +```text +full_path +https://raw.githubusercontent.com/marhar/frozen/main/space/astronauts.p1.parquet +https://raw.githubusercontent.com/marhar/frozen/main/space/astronauts.p2.parquet +https://raw.githubusercontent.com/marhar/frozen/main/space/mission_crew.p1.parquet +... +``` + +### Generating the Creation Scripts + +The file [`create-import-scripts.sql`](https://github.com/marhar/duckdb_tools/blob/main/frozen-ducklake/bin/create-import-scripts.sql) contains the logic to create the two SQL files necessary to generate the local DuckLake. + +You can customize any parameter creation logic (such as changing how table names are derived) in the `frozen_parms` table. The default code names the local DuckLake file as `myfrozen.ducklake`, which you can change when you publish. + +The generated file `tmp_create_tables.sql` contains one line for each table that looks something like this. The schema of the first Parquet file associated with each table is used to specify the schema. + +```sql +CREATE TABLE myfrozen.astronauts AS + SELECT * + FROM read_parquet('https://raw.githubusercontent.com/marhar/frozen/main/space/astronauts.p1.parquet') + WITH NO DATA; +``` + +"WITH NO DATA" is a DuckDB extension; it does the same thing as "LIMIT 0" but emphasizes that no data will be fetched or processed. + +The generated file `tmp_add_data_files.sql` should contain one line per Parquet file that looks like this, calling `ducklake_add_data_files` with the attach name, table name, and a duckdb-readable file reference. + +```sql +CALL ducklake_add_data_files( + 'myfrozen', + 'astronauts', + 'https://raw.githubusercontent.com/marhar/frozen/main/space/astronauts.p2.parquet' +); +``` + +### Creating the Local DuckLake + +After the two SQL files have been generated, run these commands in a DuckDB session. + +```sql +LOAD ducklake; +LOAD httpfs; +ATTACH 'ducklake:myfrozen.ducklake' AS myfrozen + (DATA_PATH 'tmp_always_empty'); +.read tmp_create_tables.sql +.read tmp_add_data_files.sql +``` + +The result will be a local DuckDB flavor DuckLake file called `myfrozen.ducklake`. You can attach to this DuckLake and verify your data is as you expect. Note that the `DATA_PATH` will be populated with one empty subdirectory per table. The `DATA_PATH` should otherwise be completely empty, since we only populate the Frozen DuckLake with `ducklake_add_data_files()`. During access time, this directory is not referred to, and does not need to be taken into account when publishing. Note that we could actually skip specifying the data path in this example, but we want to emphasize that (unlike a non-frozen DuckLake) that the directory is not needed. + +> **`DATA_PATH` for cloud-based Frozen DuckLakes.** Specify the data path as a cloud storage bucket, e.g., `(DATA_PATH 's3://tmp_always_empty')`, to ensure the appropriate storage module will be autoloaded when DuckDB attaches to the DuckLake. + +### Idempotent File Addition + +Note that calling `ducklake_add_data_files()` multiple times on the same file will result in the data being duplicated. A future version of this function may add an "only-once" flag; until then, we can see if the file has been added by looking at the `path` column in the `ducklake_data_file` table. + +When adding file X.parquet: + +```sql +- if X.parquet NOT IN column ducklake_data_path.path: + - CALL ducklake_add_data_files(..., X.parquet) +``` + +Note that you would have to take care that the paths are resolved correctly, as per the DuckLake documentation's [Paths page](https://ducklake.select/docs/stable/duckdb/usage/paths), For example, the two different strings `/foo/bar.parquet` and `/foo/./bar.parquet` refer to the same file. This won't be an issue if all the file paths are generated relative to the same base directory. + +### Publishing + +If you are using cloud storage, simply copy your local DuckLake file to cloud storage, e.g.: + +```batch +aws s3 cp myfrozen.ducklake s3://mybucket/space-missions.ducklake +``` + +In our GitHub-based example, we just added the DuckLake file to the repository. (Note that for real-world deployments, you probably won't be storing large databases in GitHub.) + +Note that the `DATA_PATH` specified in the `ATTACH` command will never be populated with data. It does not need to be copied to the cloud, and can be deleted once the DuckLake has been frozen. + +### Accessing the (Now Frozen) DuckLake + +Once the DuckLake file has been published to the cloud, you can access it using any of the standard DuckLake methods + +Using `ATTACH`, and providing the cloud reference: + +```sql +ATTACH 'ducklake:https://github.com/marhar/frozen/raw/refs/heads/main/space.ducklake' AS space; +USE space; +``` + +Using the DuckLake `ducklake:` syntax: + +```batch +duckdb ducklake:https://github.com/marhar/frozen/raw/refs/heads/main/space.ducklake +``` + +### Updating + +Updating a Frozen DuckLake is straightforward. The simplest method is to regenerate and publish the DuckLake file from scratch using the process above. If that's too slow, and if you are able to track which files have been newly added, you can just update the local DuckDB by calling `ducklake_add_data_files()` for the new files and republish the updated DuckLake file. + +### Versioning + +When DuckDB detects a new DuckLake version it will automatically upgrade its schema. Of course, this isn't possible for the read-only Frozen DuckLake, so you have to upgrade the DuckLake file manually. + +* Download the DuckLake file. +* Attach to the local DuckLake file with DuckDB. +* Perform any DuckLake query; `SHOW TABLES` is a convenient one. +* This triggers the DuckLake schema upgrade. +* Copy the upgraded file back to cloud storage. + +If you don't have control of the clients accessing your Frozen DuckLake it might be useful to copy your original DuckLake and publish it under a new name so that older clients can access it. + +### Executing the Workflow + +Executing the sample workflow file in the repository produces the following output... + +```batch +./sample-workflow.sh +``` + +```sql +LOAD ducklake; +LOAD httpfs; + +ATTACH 'ducklake:myfrozen.ducklake' +AS myfrozen (DATA_PATH 'tmp_always_empty'); + +CREATE TABLE myfrozen.astronauts AS + SELECT * + FROM read_parquet('https://raw.githubusercontent.com/marhar/frozen/main/space/astronauts.p1.parquet') + WITH NO DATA; + +CREATE TABLE myfrozen.mission_crew AS + SELECT * + FROM read_parquet('https://raw.githubusercontent.com/marhar/frozen/main/space/mission_crew.p1.parquet') + WITH NO DATA; + +... + +CALL ducklake_add_data_files( + 'myfrozen', + 'astronauts', + 'https://raw.githubusercontent.com/marhar/frozen/main/space/astronauts.p1.parquet' +); + +CALL ducklake_add_data_files( + 'myfrozen', + 'astronauts', + 'https://raw.githubusercontent.com/marhar/frozen/main/space/astronauts.p2.parquet' +); + +CALL ducklake_add_data_files( + 'myfrozen', + 'mission_crew', + 'https://raw.githubusercontent.com/marhar/frozen/main/space/mission_crew.p1.parquet' +); +... +``` + +```text +┌──────────────┐ +│ name │ +│ varchar │ +├──────────────┤ +│ astronauts │ +│ mission_crew │ +│ missions │ +│ spacecraft │ +└──────────────┘ +``` + +## Performance + +Creating and publishing a Frozen DuckLake with about 11 billion rows, stored in 4,030 S3-based Parquet files took about 22 minutes on my MacBook using a Wi-Fi connection. + +```text +tables: 66 +parquet files: 4030 +total parquet file size: 247.7G +total rows: 10,852,000,226 + +Preparing the build script: 1.3 seconds +Building the Frozen DuckLake: 21:47 minutes (about 3 files/sec) +``` + +## Summary + +In this blog post, we showed how to create a **Frozen DuckLake** which only uses a storage component to represent data, including a read-only DuckDB database file. We also showed how to create new revisions of a Frozen DuckLake. + +This post does not cover schema migration; if demand warrants, we'll address this topic in a future blog post. + +## Acknowledgements + +Thanks to [Jenna Jordan](https://jennajordan.me/) of Ratio PBC for reviewing and providing valuable suggestions. diff --git a/images/blog/frozen-ducklake/frozen-ducklake-creation-procedure-dark.svg b/images/blog/frozen-ducklake/frozen-ducklake-creation-procedure-dark.svg new file mode 100644 index 00000000..8616b845 --- /dev/null +++ b/images/blog/frozen-ducklake/frozen-ducklake-creation-procedure-dark.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/blog/frozen-ducklake/frozen-ducklake-creation-procedure-light.svg b/images/blog/frozen-ducklake/frozen-ducklake-creation-procedure-light.svg new file mode 100644 index 00000000..bc6dfb48 --- /dev/null +++ b/images/blog/frozen-ducklake/frozen-ducklake-creation-procedure-light.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/blog/frozen-ducklake/frozen-ducklake-overview-dark.svg b/images/blog/frozen-ducklake/frozen-ducklake-overview-dark.svg new file mode 100644 index 00000000..cea44d7d --- /dev/null +++ b/images/blog/frozen-ducklake/frozen-ducklake-overview-dark.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/blog/frozen-ducklake/frozen-ducklake-overview-light.svg b/images/blog/frozen-ducklake/frozen-ducklake-overview-light.svg new file mode 100644 index 00000000..08597f9a --- /dev/null +++ b/images/blog/frozen-ducklake/frozen-ducklake-overview-light.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/blog/frozen-ducklake/github-filelist-url.png b/images/blog/frozen-ducklake/github-filelist-url.png new file mode 100644 index 0000000000000000000000000000000000000000..b2c1cf1783fa24cb351292b9497d9363c3f7bcf9 GIT binary patch literal 37547 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 literal 0 HcmV?d00001 diff --git a/images/blog/thumbs/frozen-ducklake.png b/images/blog/thumbs/frozen-ducklake.png new file mode 100644 index 0000000000000000000000000000000000000000..63efca36e56d7ec458cf57e811005f358db8c6f7 GIT binary patch literal 30482 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 + + + + + + + + + + + + + + + + + + + + + + From 28ec11d4c048f17936d65e078253a1bf0385fbcf Mon Sep 17 00:00:00 2001 From: Gabor Szarnyas Date: Thu, 23 Oct 2025 16:30:44 +0200 Subject: [PATCH 2/5] fix urls --- _posts/2025-10-24-frozen-ducklake.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_posts/2025-10-24-frozen-ducklake.md b/_posts/2025-10-24-frozen-ducklake.md index 074359bf..2d8e79f2 100644 --- a/_posts/2025-10-24-frozen-ducklake.md +++ b/_posts/2025-10-24-frozen-ducklake.md @@ -259,14 +259,14 @@ Once the DuckLake file has been published to the cloud, you can access it using Using `ATTACH`, and providing the cloud reference: ```sql -ATTACH 'ducklake:https://github.com/marhar/frozen/raw/refs/heads/main/space.ducklake' AS space; +ATTACH 'ducklake:https://raw.githubusercontent.com/marhar/frozen/main/space.ducklake' AS space; USE space; ``` Using the DuckLake `ducklake:` syntax: ```batch -duckdb ducklake:https://github.com/marhar/frozen/raw/refs/heads/main/space.ducklake +duckdb ducklake:https://raw.githubusercontent.com/marhar/frozen/main/space.ducklake ``` ### Updating From 237d2dc9b56060f3c3c375fc55fecb69c6e4e1ed Mon Sep 17 00:00:00 2001 From: Gabor Szarnyas Date: Thu, 23 Oct 2025 16:36:37 +0200 Subject: [PATCH 3/5] Add another img to blog post --- _posts/2025-10-24-frozen-ducklake.md | 3 + .../frozen-ducklake-at-a-glance-dark.svg | 65 +++++++++++++++++++ .../frozen-ducklake-at-a-glance-light.svg | 65 +++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 images/blog/frozen-ducklake/frozen-ducklake-at-a-glance-dark.svg create mode 100644 images/blog/frozen-ducklake/frozen-ducklake-at-a-glance-light.svg diff --git a/_posts/2025-10-24-frozen-ducklake.md b/_posts/2025-10-24-frozen-ducklake.md index 2d8e79f2..65410ec7 100644 --- a/_posts/2025-10-24-frozen-ducklake.md +++ b/_posts/2025-10-24-frozen-ducklake.md @@ -11,6 +11,9 @@ excerpt: "We show how you can build high-performance data lakes with no moving p [DuckLakes](https://ducklake.select/) typically consist of two components: the catalog database and the storage. Obviously, there is no way around having some sort of storage to represent the data. But can we host a DuckLake without setting up a catalog database? In this blog post, we'll show how you can create a read-only cloud-based DuckLake without a database server. We call this a **“Frozen DuckLake”** because it is read-only and has no moving parts other than a cloud storage system. Maybe you do want to [build a snowman](https://www.youtube.com/watch?v=TeQ_TTyLGMs), too! +![Frozen DuckLake at a glance]({% link images/blog/frozen-ducklake/frozen-ducklake-at-a-glance-light.svg %}){: .lightmode-img } +![Frozen DuckLake at a glance]({% link images/blog/frozen-ducklake/frozen-ducklake-at-a-glance-dark.svg %}){: .darkmode-img } + Frozen DuckLakes have several advantages: * They have almost zero cost overhead on top of the storage of the Parquet data files. diff --git a/images/blog/frozen-ducklake/frozen-ducklake-at-a-glance-dark.svg b/images/blog/frozen-ducklake/frozen-ducklake-at-a-glance-dark.svg new file mode 100644 index 00000000..832d971a --- /dev/null +++ b/images/blog/frozen-ducklake/frozen-ducklake-at-a-glance-dark.svg @@ -0,0 +1,65 @@ + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/images/blog/frozen-ducklake/frozen-ducklake-at-a-glance-light.svg b/images/blog/frozen-ducklake/frozen-ducklake-at-a-glance-light.svg new file mode 100644 index 00000000..ff90f6c9 --- /dev/null +++ b/images/blog/frozen-ducklake/frozen-ducklake-at-a-glance-light.svg @@ -0,0 +1,65 @@ + + + + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
From f2269236d0f0e3570048dccf086afd89de0781dc Mon Sep 17 00:00:00 2001 From: Gabor Szarnyas Date: Thu, 23 Oct 2025 16:39:24 +0200 Subject: [PATCH 4/5] add time travel notice --- _posts/2025-10-24-frozen-ducklake.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/_posts/2025-10-24-frozen-ducklake.md b/_posts/2025-10-24-frozen-ducklake.md index 65410ec7..14677167 100644 --- a/_posts/2025-10-24-frozen-ducklake.md +++ b/_posts/2025-10-24-frozen-ducklake.md @@ -21,7 +21,12 @@ Frozen DuckLakes have several advantages: * They make the data immediately accessible in a SQL database with no special provisions required. * They allow data files to live in different cloud environments, while being referenced from the same Frozen DuckLake. -And, best of all, while a “Frozen DuckLake” is indeed frozen in time, the data can still be updated by creating a _new_ Frozen DuckLake – older versions can be accessed by retaining revisions of the DuckDB database file that encodes its catalog. +And, best of all, while a “Frozen DuckLake” is indeed frozen in time, the data can still be updated by creating a _new_ Frozen DuckLake. +Older versions can be accessed by retaining revisions of the DuckDB database file – or by simply using [time travel]({% link docs/stable/duckdb/usage/time_travel.md %}). For example, to travel back one week, you can use: + +```sql +FROM table AT (TIMESTAMP => (now() - "1 week"::INTERVAL)); +``` ## Designing Frozen DuckLakes From f2a9aa44af03d2d58942dc6565fb8a91f836165b Mon Sep 17 00:00:00 2001 From: Gabor Szarnyas Date: Fri, 24 Oct 2025 07:31:14 +0200 Subject: [PATCH 5/5] Add half sentence --- _posts/2025-10-24-frozen-ducklake.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_posts/2025-10-24-frozen-ducklake.md b/_posts/2025-10-24-frozen-ducklake.md index 14677167..23f76075 100644 --- a/_posts/2025-10-24-frozen-ducklake.md +++ b/_posts/2025-10-24-frozen-ducklake.md @@ -107,7 +107,7 @@ LIMIT 4; └─────────────────────────────┴──────────────┴────────────────────────────────────────────────┘ ``` -This query was served from a Frozen DuckLake, using only storage. +This query was served from a Frozen DuckLake, using only storage; you can see the files in the GitHub repo. ## Creating and Freezing a DuckLake