You have an app to write, and before you can write any of it you owe somebody a sign-in screen. Then a way to take money. Then somewhere to put the files people upload. Each one is a week, or it is a vendor, and the vendor is a week too — a different week, spent reading somebody else’s dashboard instead of your own code.
Pithy is the other option. It is an open-source backend kit for Cloudflare: a set of capability packages that compose into a Worker you own, on a Cloudflare account you own, against a D1 database you own. Auth, payments, storage, media, semantic search, games, mail, language. You add the ones you need, and the ones you do not add are not there.
There is no Pithy-operated service anywhere in the request path. Not as a policy — as an architecture. We do not run a thing your traffic could go through.
The smallest real example
Four commands take an empty directory to a deployed Worker.
pithy init
pithy add auth --with-prerequisites
pithy migrate --env dev
pithy devWhat pithy init leaves behind is small on purpose. Your whole Worker is this:
import { createEntrypoint } from "@pithy-sh/core/src/createEntrypoint";
import config from "../pithy.config";
export default createEntrypoint(config);And your app is a capability like any other one — routes, middleware, tables, and the bindings they need:
const app = defineCapability({
name: "app",
requiredBindings: [{ type: "d1", name: "DB" }],
routes: (a) => {
a.get("/hello", requireAuth(), (c) => c.json({ hi: c.var.auth?.userId }));
},
});requireAuth() came from @pithy-sh/auth. You did not write a session check, a token parser, or a JWKS fetch, and none of that code is in your repository — it is in the package, and it upgrades when the package does. The Worker contract covers what createEntrypoint assembles and what is on c.var when your handler runs.
What you own
Everything. That sentence is short because the architecture is.
- The Worker runs in your Cloudflare account, under your own script name, on your own bill.
- The data is in your D1, your KV, your R2. Every table a capability creates is prefixed
pithy_<capability>_, sitting in the same database as your own tables, joinable with plain SQL. - The source is MIT-licensed.
pithy add <capability> --ejectcopies a capability into your repository and repoints the wiring at your copy, if the day comes that you want it.
The surface you maintain is deliberately thin: a pithy.config.ts per Worker, a wrangler.jsonc, and a mount file. The logic lives in the packages, which is what makes an upgrade a version bump rather than a merge.
What it costs you
Fair is more useful than flattering, so: this is not free, and it is not zero-operations.
You run a Cloudflare account. Workers, D1, KV, R2, Vectorize, Workflows and Durable Objects are metered, and the bill is yours. For most apps that is single-digit dollars a month, and for a busy multiplayer queue it is not — every capability that can cost real money ships a costs page saying which meter it turns.
You are the operator. Nobody pages you at 3 a.m., because Cloudflare runs the platform. But schema promotion, secret rotation and provisioning are commands you run, and the day one of them fails, you are the one reading the error.
Some of it is your problem on purpose. Pithy takes no position on whether your ledger units are money, and any regulation that implies is yours. Storage stores bytes and does not decide what they are. Payments resolves entitlements and does not do your tax.
It is Cloudflare-only. There is no Postgres adapter and there will not be one. If your backend needs to run somewhere else, this is the wrong kit, and Is Pithy for you? says so at greater length.
Three doors out
- Build something. Install, then the Quickstart — an empty directory to a Worker answering on localhost, in about five minutes, with no Cloudflare account.
- Browse what composes. The capability catalog is every capability, one line each, and what each one composes with.
- Understand the model first. What is a capability? and One project, or two? are the two ideas everything else is built on, and the second one is the most expensive question to answer wrong.