Skip to content

Bindings

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?

Bindings expose resources to your code at runtime. For example, they allow a Cloudflare Worker to access:

  • KV Namespaces
  • Durable Objects
  • R2 Buckets
  • Secrets and variables

Using Bindings in Workers

typescript
// alchemy.run.ts
import { Worker, KVNamespace } from "alchemy/cloudflare";

// Create a KV namespace
const myKV = await KVNamespace("MY_KV", {
  title: "my-kv-namespace"
});

// Bind the KV namespace to a worker
const myWorker = await Worker("my-worker", {
  name: "my-worker",
  entrypoint: "./src/worker.ts",
  bindings: {
    MY_KV: myKV,
    API_KEY: "secret-key",
    DEBUG_MODE: true
  }
});

The worker can then access these bindings through the env parameter:

typescript
// src/worker.ts
export default {
  async fetch(request: Request, env: any, 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.DEBUG_MODE;
    
    return new Response(`Value: ${value}`);
  }
};

Type-Safe Bindings

To make bindings type-safe, create an env.d.ts file:

typescript
/// <reference types="./env.d.ts" />

import type { myWorker } from "./alchemy.run";

export type WorkerEnv = typeof myWorker.Env;

declare module "cloudflare:workers" {
  namespace Cloudflare {
    export interface Env extends WorkerEnv {}
  }
}

Then, use the type in your worker:

typescript
// src/worker.ts
export default {
  async fetch(request: Request, env: Cloudflare.Env, 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}`);
  }
};

Binding Types

Alchemy supports several binding types:

Binding TypeDescriptionExample
KV NamespaceKey-value storageMY_KV: myKV
Durable ObjectStateful objectsCOUNTER: counter
R2 BucketObject storageSTORAGE: bucket
SecretSensitive valueAPI_KEY: alchemy.secret("key")
VariablePlain text valueDEBUG: "true"

Binding Resources vs Values

Alchemy handles bindings differently based on what's being bound:

typescript
const worker = await Worker("worker", {
  // ...
  bindings: {
    // Resource bindings (automatically set up in Cloudflare)
    KV_STORE: kvNamespace,
    COUNTER: durableObject,
    BUCKET: r2Bucket,
    
    // Value bindings (passed as environment variables)
    API_KEY: alchemy.secret(process.env.API_KEY),
    DEBUG: "true",
    VERSION: "1.0.0"
  }
});