Skip to content
Guide

Distributing a worker

Your worker runs. Now decide who else gets to ATTACH it — your team, anyone with a GitHub link, or paying customers on the Orchard — and what you have to ship for each.

A worker is useful the moment it runs on your machine. It becomes infrastructure when somebody else can attach it without asking you how. That step is a packaging and hosting decision, and it's the same decision whichever language you built it in.

The decision

Three ways to share a worker

They aren't exclusive — plenty of workers start internal, go open source, and end up listed. Each one asks more of you and gives the user more in return.

Keep it internal

Audience: Your team

Run the worker on your own infrastructure and hand colleagues the ATTACH line, or check the script into the repo they already clone. Nothing is published; access is whatever your network and auth already enforce.

No release process. You own hosting and support.

Publish on GitHub

Audience: Anyone

Put the source in a public repo, tag releases, and ship an artifact people can run — a package, a binary, or a container image. Users supply their own compute, so you host nothing.

You own the code and the docs. Users own the running.

List it on the Orchard

Audience: Customers

Submit the worker to Query.Farm’s connector marketplace. It gets a listing, a catalog entry, and managed credentials — and you can charge for it, with billing handled for you.

You host the worker; Query.Farm handles billing and distribution.

Packaging

Ship a process, or run a service

Underneath all three routes there are only two shapes, and they differ in who runs the worker.

As a process, you publish an artifact and the user's DuckDB spawns it locally over pipes. You host nothing, there is no uptime to keep, and their data never leaves their machine — but they need the runtime installed, and every user runs their own copy.

As a service, you deploy the worker once and hand out a URL. Users attach it with no install at all, you can update it without anyone upgrading, and you can authenticate, meter, and rate-limit callers — in exchange for owning the hosting bill and the pager.

what the user runs
-- Distributed as a process: users run it themselves.
--   A published package, launched on demand …
ATTACH 'my_worker' AS mw (TYPE vgi, LOCATION 'uvx [email protected]');

--   … or a container image, over the same pipe transport.
ATTACH 'my_worker' AS mw (TYPE vgi, LOCATION 'docker run --rm -i ghcr.io/you/my-worker:1.2.0');

-- Distributed as a service: you run it, they attach a URL. Needs HTTP.
ATTACH 'my_worker' AS mw (TYPE vgi, LOCATION 'https://my-worker.example.com/');

The worker source is the same in both cases; only the transport it's started with changes. See Architecture for the hosting options — load balancers, Cloudflare Workers, Cloud Run, Lambda — and Connect to a worker for every LOCATION form a user can type.

Open source

Publishing on GitHub

The simplest way to share a worker with the world is a public repository and tagged releases. There is no registry to apply to and no review to pass — a VGI worker is just a program, so whatever your language already uses for distribution works here.

01

A runnable artifact, not just source

Publish to the registry your language already uses — PyPI, npm, crates.io, Maven Central, Go modules — or push a container image to GHCR. That is what makes LOCATION 'uvx my-worker' or a docker run command work without a clone-and-build step.

02

The ATTACH line in the README, first

The first thing a reader needs is the exact statement that makes your worker appear as SQL, followed by one query that returns rows. Everything else can come after.

03

Tagged releases, pinned versions

Cut a GitHub release per version and let users pin it. A worker they attach in a scheduled job should not change under them because you pushed to main.

04

Version the schema, not just the code

The catalog you expose is an interface. Renaming a column or changing a type breaks somebody’s query as surely as changing a function signature — treat it as a breaking change and say so in the release notes.

05

A way to self-host it

If the worker serves HTTP, include a Dockerfile and a deploy config (Fly, Cloud Run, Lambda, or plain systemd) so a user can stand up their own copy instead of trusting yours.

06

Docs for every table, function, and credential

Descriptions travel over the protocol and show up in DuckDB’s own introspection, so writing them once pays off in the SQL client too.

Published something? Tell us — we're happy to point people at it, and to help if you'd rather it were listed and billed for you.

Monetize

Listing it on the Orchard

The Orchard is Query.Farm's connector marketplace: workers a DuckDB user can subscribe to and attach with one line of SQL. If what you've built is worth paying for — a proprietary dataset, an expensive-to-run model, a service you already sell — listing it turns the worker into a product without you building a billing system, a credential store, or a distribution channel.

You keep running the worker. Query.Farm handles the commercial side and pays out a revenue share on subscriptions.

What Query.Farm handles

  • Billing and subscriptions, with a revenue share paid back to you.
  • Credentials — users get an Orchard token instead of hand-managed secrets.
  • Distribution and discovery: a catalog listing beside every other connector.
  • Review for correctness, security, and a clean, stable schema before it goes live.

What a listing needs

  • A worker that runs as a hosted service — so an SDK that serves HTTP.
  • A stable schema that will not change without versioning.
  • Auth through DuckDB secrets or Orchard tokens, never hard-coded.
  • A runnable example query that returns rows.
  • Clear docs for each table, function, and required credential.
In preview

The Orchard is in preview, so exact revenue-share terms are agreed during onboarding and the listing manifest is still changing. The publishing guide has the current process, the manifest format, and the review checklist.

Before you publish

What changes when other people attach it

A worker you use yourself can be forgiving. One other people attach is an interface with users who can't read your code and won't file a good bug report. Four things are worth doing before you hand out the URL, whichever route you take.

Errors a stranger can act on

A failure inside your worker surfaces in the middle of somebody’s query. “Upstream API returned 429, retry after 30s” is useful; a stack trace is not.

Limits and timeouts

Decide what happens when a query asks for far more than you expected — cap it, page it, or fail fast. A shared worker is a shared resource.

Auth at the source

If different callers should see different rows, enforce it in the worker rather than documenting it. Row and column security is part of the protocol.

An example that actually runs

One query, real output. It is both your smoke test and the thing that convinces someone to attach it.

If the worker exposes data with per-customer rules, do that work in the worker rather than in documentation — see row & column security and authentication.

Where to from here

Want it built, hosted, or listed for you?

We build and operate VGI workers for clients, and we run the Orchard.