A binding name never carries the project. It is a variable name inside your own Worker, and two projects cannot collide on it — only the resource it resolves to is scoped.
By capability
Every name here is held to the naming rules, the databases behind them carry these tables, what a Worker must declare is the Worker contract, and the class-migration half is Durable Objects.
| Capability | Binding | Kind | |
|---|---|---|---|
| auth | DB | D1 | |
AUTH_RATE_LIMITER | Rate limiting | The coarse per-IP edge guard | |
| payments | DB | D1 | |
PAYMENTS_RECONCILE | Workflow | Optional | |
| storage | DB | D1 | |
STORAGE_BUCKET | R2 | ||
STORAGE_SWEEP | Workflow | Optional | |
| media | DB | D1 | |
MEDIA_BUCKET | R2 | ||
MEDIA_IMAGE_TO_TEXT | Workflow | Optional | |
MEDIA_AUDIO_TRANSCRIBE | Workflow | Optional | |
MEDIA_VIDEO_TRANSCRIBE | Workflow | Optional | |
MEDIA_DOC_EXTRACT | Workflow | Optional | |
DB | D1 | ||
EMAIL_SUPPRESSIONS | D1 | Shared across environments | |
EMAIL_SENDER | Workflow | ||
| vector | VECTORIZE | Vectorize | Remote |
AI | Workers AI | Remote | |
DB | D1 | ||
VECTOR_REPROCESS | Workflow | Optional | |
| secrets | SECRETS | D1 | Its own database |
SECRETS_ENCRYPTION_KEYS | Secrets Store | The master key | |
| support | DB | D1 | |
SUPPORT_BUCKET | R2 | Optional | |
SUPPORT_CLASSIFY | Workflow | Optional | |
| testers | DB | D1 | |
TESTERS_DAILY | Workflow | Optional | |
| audit | DB | D1 | |
| ledger | DB | D1 | |
| leaderboard | DB | D1 | |
| rating | DB | D1 | |
| multiplayer | SESSIONS | Durable Object | MultiplayerSession |
DB | D1 | ||
| matchmaking | DB | D1 | |
MATCHMAKING | KV | Room codes | |
QUEUE | Durable Object | MatchmakingQueue | |
PRESENCE | Durable Object | MatchmakingPresence | |
| core | DB | D1 | |
CONTROL_PLANE | KV | Optional — only the KV replay backend | |
| i18n, turnstile | — | No bindings at all |
DB is shared on purpose
Most capabilities default to DB, the shared app database, so an admin Worker and an API Worker read the same rows without wiring.
One capability’s tables cannot collide with another’s, because every one is pithy_<capability>_*.
Two that are deliberately not DB
SECRETS is its own database, because the master key that opens its rows is per environment.
EMAIL_SUPPRESSIONS is shared across a project’s environments — because an unsubscribe has to apply everywhere, and somebody who opted out in production has not agreed to receive staging’s mail.
Optional means the capability works without it
A missing optional Workflow binding is a feature that does not run, not a Worker that will not boot.
Storage without its sweep still uploads; abandoned rows simply are not reclaimed. Media without its enrichment Workflows still stores files.
The exception that bites is core/missing_workflow_binding — a Workflow binding pointing at a host nothing has provisioned. That is the first-run surprise.
What pithy add can and cannot write
add writes bindings and touches no account. That is why adding a capability works offline, in CI, and without credentials.
Three kinds it cannot finish:
A vectorize entry needs an index_name that provisioning produces.
A workflows entry needs a name and a class_name, both per environment — and a partial entry stops wrangler loading the config at all, so add writes none.
A kv_namespaces entry has no name field, so add prints the name to create and you paste the id in.
Durable Object classes are exported from their own modules
export { MultiplayerSession } from "@pithy-sh/multiplayer/src/session/durableObject";
export { MatchmakingQueue } from "@pithy-sh/matchmaking/src/queue/durableObject";
export { MatchmakingPresence } from "@pithy-sh/matchmaking/src/presence/durableObject";Each also needs a class-migration tag, in a different block, repeated per environment. A binding without the tag deploys a Worker whose class does not exist.