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.
-- 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.
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.
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.
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.
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.
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.
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.
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
Building a Worker
Scope, capabilities, and choosing a language.
Publish on the Orchard
The listing process, manifest, and requirements.
Data-as-a-Service
Selling access to data as an attachable catalog.
Authentication
Tokens, secrets, and identity on the way in.
Want it built, hosted, or listed for you?
We build and operate VGI workers for clients, and we run the Orchard.