Binding
Bindings allow resources to connect to each other in a type-safe way. In Alchemy, bindings are most commonly used with Cloudflare Workers to give them access to other resources.
What are Bindings?
Section titled “What are Bindings?”Bindings expose resources to your code at runtime. For example, they allow a Cloudflare Worker to access:
- Environment variables (non-sensitive strings)
- Secrets (sensitive strings)
- Resources like KV Namespaces, Durable Objects, R2 Buckets, etc.
Using Bindings in Workers
Section titled “Using Bindings in Workers”import { Worker, KVNamespace } from "alchemy/cloudflare";
// Create a KV namespaceconst myKV = await KVNamespace("MY_KV", { title: "my-kv-namespace"});
// Bind the KV namespace to a workerconst myWorker = await Worker("my-worker", { name: "my-worker", entrypoint: "./src/worker.ts", bindings: { // an environment variable (non-sensitive) STAGE: "prod", // a secret (sensitive) API_KEY: alchemy.secret("secret-key"), // a resource (binds as an object with methods) MY_KV: myKV, }});
The worker can then access these bindings through the env
parameter:
import type { myWorker } from "../alchemy.run.ts";
export default { async fetch(request: Request, env: typeof myWorker.Env, ctx: any) { // Access the KV namespace binding const value = await env.MY_KV.get("key");
// Access other bindings const apiKey = env.API_KEY; const isDebug = env.STAGE === "prod";
return new Response(`Value: ${value}`); }};
Type-Safe Bindings
Section titled “Type-Safe Bindings”Alchemy does not use code-generation. Instead, the runtime types of your bindings can be inferred in two ways:
- Use a type-only import to infer from your worker definition in
alchemy.run.ts
import type { myWorker } from "./alchemy.run";
export default { async fetch(request: Request, env: typeof myWorker.Env, ctx: any) { env.MY_KV.get("key"); // allowed env.NON_EXISTING_BINDING; // type error }}
- Augment
env
from thecloudflare:workers
module to infer the types globally:
import type { myWorker } from "./alchemy.run";
export type WorkerEnv = typeof myWorker.Env;
declare module "cloudflare:workers" { namespace Cloudflare { export interface Env extends WorkerEnv {} }}
Register env.ts
in your tsconfig.json
’s types
.
{ "compilerOptions": { "types": ["@cloudflare/workers-types", "./src/env.ts"] }}
Then, use the type in your worker:
export default { async fetch(request: Request, env: WorkerEnv, ctx: any) { // Type-safe access to bindings const value = await env.MY_KV.get("key"); const apiKey = env.API_KEY;
return new Response(`Value: ${value}`); }};
Or use the global import:
import { env } from "cloudflare:workers";
await env.MY_KV.get("key")
Binding Types
Section titled “Binding Types”Alchemy supports three types of bindings:
Strings
Section titled “Strings”For non-sensitive configuration values (visible in logs):
const worker = await Worker("my-worker", { bindings: { STAGE: app.stage, VERSION: "1.0.0", DEBUG_MODE: "true" }});
Secrets
Section titled “Secrets”For sensitive values like API keys (always use alchemy.secret()
):
const worker = await Worker("my-worker", { bindings: { API_KEY: alchemy.secret("secret-key"), DATABASE_PASSWORD: alchemy.secret("db-pass") }});
Resources
Section titled “Resources”For infrastructure connections:
import { Worker, KVNamespace, R2Bucket } from "alchemy/cloudflare";
const kvStore = await KVNamespace("MY_KV", { title: "my-kv-namespace" });const bucket = await R2Bucket("MY_BUCKET", { name: "my-storage-bucket" });
const worker = await Worker("my-worker", { bindings: { KV_STORE: kvStore, STORAGE: bucket, STAGE: app.stage, API_KEY: alchemy.secret("key") }});