The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

ducklake is an R package that brings versioned data lake infrastructure to data-intensive workflows. Built on DuckDB and DuckLake, it provides ACID transactions, automatic versioning, time travel queries, and complete audit trails.
Many industries rely on flat-file workflows (CSV, XPT, Excel, etc.) that create significant data management challenges:
DuckLake solves these problems by implementing a versioned data lake architecture that:
install.packages("ducklake")pak::pak("tgerke/ducklake-r")ducklake requires the duckdb R package version 1.5.1 or newer (DuckDB engine 1.5.1+, matching the stable DuckLake v1.0 specification). The Quack remote-access features are the exception: they need DuckDB 1.5.3 or newer, which means duckdb 1.5.4 or newer from CRAN.
DuckLake itself ships as a DuckDB extension that is downloaded on
first use. Run install_ducklake() once per machine, or
check whether you already have it with
ducklake_extension_available().
ducklake manages its own DuckDB connection, so there is nothing to
set up: just attach_ducklake() and go. If you prefer to
supply your own connection (for example, one shared with other DBI-based
tools), register it with set_ducklake_connection().
library(ducklake)
library(dplyr)
# Install the ducklake extension (requires duckdb R package >= 1.5.1)
install_ducklake()
# Create a data lake in a temporary directory
attach_ducklake("my_data_lake", lake_path = tempdir())
# Bronze layer: Load raw data exactly as received
with_transaction(
create_table(mtcars, "vehicles_raw"),
author = "Data Engineer",
commit_message = "Initial load of raw vehicle data"
)
# Silver layer: Apply cleaning transformations
with_transaction(
get_ducklake_table("vehicles_raw") |>
mutate(cyl = as.character(cyl)) |>
create_table("vehicles_clean"),
author = "Data Engineer",
commit_message = "Clean and standardize vehicle data"
)
# Gold layer: Create analysis dataset with business logic
with_transaction(
get_ducklake_table("vehicles_clean") |>
mutate(
efficiency = case_when(
mpg < 15 ~ "Low",
mpg < 25 ~ "Medium",
TRUE ~ "High"
)
) |>
create_table("vehicles_analysis"),
author = "Data Analyst",
commit_message = "Create analysis-ready dataset with efficiency categories"
)
# Update the silver layer with additional transformations
with_transaction(
get_ducklake_table("vehicles_clean") |>
mutate(gear = as.integer(gear)) |>
replace_table("vehicles_clean"),
author = "Data Engineer",
commit_message = "Add gear type conversion to silver layer"
)
# View the analysis dataset
get_ducklake_table("vehicles_analysis") |>
select(mpg, cyl, efficiency) |>
head(3)
#> # A query: ?? x 3
#> # Database: DuckDB 1.5.1 [tgerke@Darwin 25.5.0:R 4.5.2//private/var/folders/b7/664jmq55319dcb7y4jdb39zr0000gq/T/RtmpwGZIaL/ducklake/ducklake58b075fac717.duckdb]
#> mpg cyl efficiency
#> <dbl> <chr> <chr>
#> 1 21 6.0 Medium
#> 2 21 6.0 Medium
#> 3 22.8 4.0 Medium
# View complete audit trail across all layers with author and commit messages
list_table_snapshots()
#> snapshot_id snapshot_time schema_version
#> 1 0 2026-08-25 21:02:58 0
#> 2 1 2026-08-25 21:02:58 1
#> 3 2 2026-08-25 21:02:58 2
#> 4 3 2026-08-25 21:02:58 3
#> 5 4 2026-08-25 21:02:58 4
#> changes
#> 1 schemas_created, main
#> 2 tables_created, tables_inserted_into, main.vehicles_raw, 1
#> 3 tables_created, tables_inserted_into, main.vehicles_clean, 2
#> 4 tables_created, tables_inserted_into, main.vehicles_analysis, 3
#> 5 tables_created, tables_dropped, tables_inserted_into, main.vehicles_clean, 2, 4
#> author commit_message
#> 1 <NA> <NA>
#> 2 Data Engineer Initial load of raw vehicle data
#> 3 Data Engineer Clean and standardize vehicle data
#> 4 Data Analyst Create analysis-ready dataset with efficiency categories
#> 5 Data Engineer Add gear type conversion to silver layer
#> commit_extra_info
#> 1 <NA>
#> 2 <NA>
#> 3 <NA>
#> 4 <NA>
#> 5 <NA>
# Time travel: Query the silver layer as it existed at snapshot 2 (before updates)
get_ducklake_table_version("vehicles_clean", version = 2) |>
select(mpg, cyl, gear) |>
head(3)
#> # A query: ?? x 3
#> # Database: DuckDB 1.5.1 [tgerke@Darwin 25.5.0:R 4.5.2//private/var/folders/b7/664jmq55319dcb7y4jdb39zr0000gq/T/RtmpwGZIaL/ducklake/ducklake58b075fac717.duckdb]
#> mpg cyl gear
#> <dbl> <chr> <dbl>
#> 1 21 6.0 4
#> 2 21 6.0 4
#> 3 22.8 4.0 4
# Clean up
detach_ducklake("my_data_lake")ducklake implements a layered data architecture (medallion pattern) that ensures data quality and traceability:
Each layer is automatically versioned, providing complete data lineage from raw source through to analysis-ready datasets. This approach enables:
ducklake tracks lineage at the table level: which tables changed at each snapshot, and why. For lineage within a query — which source columns feed each output column — the companion package dplyneage picks up where ducklake leaves off. Lake tables are ordinary dbplyr lazy tables, so any query pipes straight into an interactive diagram:
library(dplyneage)
get_ducklake_table("orders") |>
dplyr::left_join(get_ducklake_table("customers"), by = "customer_id") |>
dplyr::group_by(region) |>
dplyr::summarise(total_sales = sum(amount, na.rm = TRUE)) |>
extract_lineage() |>
lineage_flow()dplyneage’s ducklake lineage vignette walks through a full example, including per-layer diagrams for medallion pipelines and lineage for time-travel queries.
Check out the pkgdown site for detailed vignettes:
rows_*, upserts, merge_into(), and
replace_table()attach_ducklake(snapshot_version = ...)set_table_partitioning()) and
sorted tables (set_table_sorting()) prune files on large
tablesadd_data_files() registers existing Parquet files with the
lake without copying or rewriting themcreate_storage_secret() handles credentialsset_ducklake_option() adjusts
DuckLake’s persisted settings (compression, file sizes, commit-message
policy) at lake, schema, or table scopeadd_table_column(), drop_table_column(),
rename_table_column(), set_column_type(), and
rename_ducklake_table() change a table’s shape as
metadata-only operations — no data rewrite, and every earlier schema
stays reachable through time travelcreate_table() stores haven/labelled column labels as
catalog comments and collect() restores them, so gtsummary
and gt keep displaying them; set_table_comment(),
set_column_comments(), and
get_table_comments() manage documentation any client of the
lake can readcreate_view() stores a dplyr
pipeline as a SQL view in the lake — shared logic that always reads
current data; list_ducklake_tables() shows what’s
thereattach_ducklake(encrypted = TRUE)rows_insert(), rows_update(),
rows_delete(), and rows_upsert() for
incremental changes; merge_into() for conditional merges
and staging-table syncs; replace_table() pipelines for bulk
rewrites — all fully versionedThese binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.