Layout
The files of a repository, their paths, and the content of fdl.json.
Paths
Paths are relative to the root, lower case, and separated by /. The root is what a bare Git repository is on a server, for example s3://bucket/lake/.
<root>/
fdl.json repository settings
HEAD the default ref: "ref: refs/heads/main"
refs.json every ref and the version it holds, for readers that cannot list
refs/
heads/<name> branches. They move; main is what readers see by default
tags/<name> tags. Never moved once made
requests/<number> for the host's own use, such as pending approvals (optional)
versions/<version ID>/
version.json the version record, written last
version.json.sig a signature of the record (optional)
ducklake.duckdb the frozen catalog
dataset.json what the version holds, described
files.json each table's data files, indexed from the catalog (optional)
catalogs/<format>.duckdb the catalog in another DuckLake format (optional)
expired.json the past-retention mark (only once expired)
<others> files a host adds, such as previews
<data_dir><schema>/<table>/ducklake-<uuid>.parquet data files (shared, immutable)
sources/<sha256> source files (optional, may be private)
HEAD and everything under refs/ have no extension, as in Git. Their content is UTF-8 text.
The root must not hold a DuckLake catalog outside versions/, and must never hold a working catalog. Either would give readers a state that was never published.
Files with other names may sit at the root. Readers must ignore them.
fdl.json
{
"fdl": "0.1",
"id": "5f0c8a52-6d3e-4f8e-9b1a-2c7d4e9f0a13",
"data_dir": "data/",
"signers": ["alice@example.org ssh-ed25519 AAAAC3…"],
"catalog_formats": [
{ "ducklake": "1.1" },
{ "ducklake": "1.0", "until": "2027-03-31" }
]
}
| Field | Required | Meaning |
|---|---|---|
fdl |
must | The version of this specification. A reader must not read a major version it does not know |
id |
should | A UUID written when the repository is started and never changed |
data_dir |
may | Where data files are, relative to the root, ending in /. Default data/ |
catalog_formats |
may | The DuckLake formats published for new versions, and until when |
signers |
may | Public keys that sign versions, as lines of an SSH allowed_signers file |
fdl.json is created with If-None-Match: *, so starting a repository twice leaves the first one’s settings in place.
id
The id lets a copy of the repository tell that it holds the same one. Mirrors keep it as it is. A host may write its own ID for the dataset here when it starts the repository. A repository without an id is still read.
data_dir
The default is data/. A repository whose data files already sit under another prefix declares that prefix here instead of moving them. Every data file a catalog names must be under data_dir.
signers
The keys the repository’s writers sign versions with (see Reading). A reader must not trust a key because it is listed here: a mirror can change fdl.json too. The list tells a reader which keys to expect, and the reader gets the keys it trusts from the origin by other means.
How long versions are kept is not declared here. It is the host’s decision.
catalog_formats
Each entry names a DuckLake format and, optionally, the last day it is written for new versions (until, an ISO 8601 date). Without the field, versions carry only ducklake.duckdb. See Versions.