Skip to main content

DuckLess

PyPI Docs License

Documentation · Quickstart · Examples · Benchmarks · Releases · Contributing

Serverless DuckDB on GCP. Submit SQL or your own code; DuckLess runs it in your project on a right-sized machine (Cloud Batch VM with local SSD for spill, or Cloud Run Jobs for small jobs), reads and writes GCS with the job's own credentials (no HMAC keys), then tears it down. Nothing runs between jobs. Jobs read Parquet, CSV, JSON, Excel and BigQuery tables, and write BigQuery tables; optional DuckLake tables on a Cloud SQL catalog, and Agent Skills for coding agents.

Status: v0.4, young and tested on real projects. Changes are listed in the GitHub Releases; the benchmarks have the measurements behind the design.

Quick start

uv tool install duckless                     # or: pip install duckless

duckless init --project my-project --region europe-west1
# prints the lines to put in .envrc (DUCKLESS_PROJECT, DUCKLESS_BUCKET, DUCKLESS_SA, DUCKLESS_IMAGE)

duckless preflight --machine n2-highmem-32 --spot
duckless run job.sql --machine n2-highmem-32 --spot
duckless exec --image <your-image> --machine n2-highmem-16 -- dbt build
duckless status <job-id>
duckless logs <job-id> --follow
duckless result <job-id>
duckless destroy --project my-project       # removes what init created

duckless init is optional. It applies the Terraform module shipped with each release (duckless/terraform) through Infrastructure Manager: handy to start in five minutes. Teams that keep their infrastructure as code call the same module from their own Terraform and CI/CD instead, with their deployment identity, and never run init:

module "duckless" {
  source           = "git::https://github.com/tosun-si/duckless.git//duckless/terraform?ref=v0.4.2"
  project_id       = "my-project"
  region           = "europe-west1"
  runner_image_tag = "0.4.2"
}

The CLI only reads the settings the module outputs (envrc), however they were created.

Full guide: tosun-si.github.io/duckless, from the quickstart to the CLI reference.

Writing jobs

  • SQL (.sql): ${VAR} placeholders come from the job env (DUCKLESS_BUCKET, --env K=V).

  • Python (.py): from duckless_runtime import connect gives a DuckDB connection with GCS auth, spill on local SSD, memory and threads sized to the VM.

  • Write to GCS in parallel: COPY … TO 'gs://…' (FORMAT parquet, PER_THREAD_OUTPUT, FILE_SIZE_BYTES '256MB') is 7-8x faster than the single-writer default (~900 MB/s vs ~110 MB/s on 32 vCPU).

  • Vectorize Python logic: a row-wise Python UDF runs at ~8k rows/s on one thread; use an Arrow UDF over numpy (type="arrow") or SQL.

  • Read BigQuery: bigquery_scan('project.dataset.table', filter = '…') in SQL, read_bigquery(con, table, columns, where) in Python; only the columns and rows asked for leave BigQuery (duckless init --bigquery-dataset <dataset> first).

  • Write BigQuery: to_bigquery(con, query, "project.dataset.table", mode=...): Parquet, a free load job, then replace_partitions (deletes whole partitions for free, bills only the new rows) or a merge that reads only the partitions it touches (guide; duckless init --bigquery-write-dataset <dataset> first).

More in Writing jobs and Machines, Spot and spill.

Examples

Runnable pipelines in examples/, on data generated by the first one:

Example What it shows
01-daily-marts raw Parquet to marts in plain SQL
02-ducklake-incremental CSV loads and late JSON corrections in a DuckLake table, time travel
03-raw-validation validating a raw CSV against YAML rules: 100 million lines in about a minute
04-soda-contracts the same checks as a Soda v4 data contract, verified through DuckDB
05-bigquery-to-python a BigQuery table, scored by vectorized NumPy logic, written to GCS

Agent Skills

DuckLess ships a Claude Code plugin with five skills: setup, writing-jobs, sizing, troubleshooting and ducklake. They carry what the docs and the CLI cannot decide for you (which machine, why a job failed) and the rules measured while building DuckLess.

duckless skills install          # into this project: .claude/skills + .agents/skills (--user: your home)

Or as a Claude Code plugin, kept up to date from this repository:

/plugin marketplace add tosun-si/duckless
/plugin install duckless@duckless

Layout

Hexagonal, kept light: a pure core, ports, adapters, and one wiring point.

Path What
duckless/core/ Pure rules, no I/O: machine types and local SSD counts, job spec and planning, quotas, preflight
duckless/ports.py What the service needs from outside: Executor, ArtifactStore, LogReader, QuotaReader, InfraBootstrap, InfraDeployer (Protocols)
duckless/service.py Operations shared by the CLI, the SDK and later the SaaS control plane: functions taking ports as arguments
duckless/adapters/ GCP implementations: Cloud Batch, Cloud Run Jobs, GCS, Cloud Logging, Compute quotas, Infrastructure Manager
duckless/wiring.py Binds the service functions to the adapters (lazily)
duckless/cli.py duckless command, a driving adapter
runtime/ Runner image (duckless_runtime), published as ghcr.io/tosun-si/duckless-runner: DuckDB with the gcs, bigquery, ducklake, excel, avro and iceberg extensions, the Cloud SQL Auth Proxy, tuned for the machine
examples/ Runnable pipelines, with the unit tests of their logic
duckless/terraform/ The Terraform module (callable from your own Terraform): APIs, work bucket, least-privilege runner service account, Artifact Registry remote repository proxying the runner image, optional DuckLake catalog and BigQuery access
duckless/plugin/ Claude Code plugin: the Agent Skills (duckless/plugin/skills/), listed by .claude-plugin/marketplace.json
spike/ The spike that validated the approach, kept as a record

Dependency rule: core imports nothing else from DuckLess, service only core and ports, and only wiring imports adapters.

Contributing

Issues and pull requests are welcome: bug reports, real use cases, docs, code. See CONTRIBUTING.md for the setup, the conventions and how changes are tested.

uv sync
uv run pytest
uv run ruff check . && uv run ruff format --check .

License

DuckLess is open source under the Apache License 2.0. You can use it, modify it and ship it, commercially or not; keep the license and the notices.

Metadata

Release files for duckless 0.4.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for duckless 0.4.2
File Size Uploaded
duckless-0.4.2.tar.gz 55.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for duckless 0.4.2
File Interpreter ABI Platform
duckless-0.4.2-py3-none-any.whl Python 3 none any Details

Total release size: 127.2 kB

Release files / duckless-0.4.2.tar.gz

Download URL duckless-0.4.2.tar.gz
Size 55.6 kB
Tags Source
SHA-256 checksum
How to use checksums
806272dd927ea27c215def151bcaab0b69221d095f2c352eff88bcc6f17e692b
BLAKE2b-256 checksum
How to use checksums
6c225f5fc37855ea5feb1872b751bf02b72927499e5f6d8eccf51cc75999966a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release files / duckless-0.4.2-py3-none-any.whl

Download URL duckless-0.4.2-py3-none-any.whl
Size 71.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1f4d58cb9bff4b2bab7e8ff1832d0e889603ef8794a0d2de67df18cb9dd92f58
BLAKE2b-256 checksum
How to use checksums
8ba40716f98a84e73baa6ca3686a33d6f93a9ef50a524f49b0f08c9b049bf572
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.3

2 release files

This release

0.4.2 This release

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page