Files
gh-tenequm-claude-plugins-c…/skills/skill/references/bindings-complete-guide.md
2025-11-30 09:01:09 +08:00

13 KiB

Complete Bindings Guide

Bindings are how Workers connect to Cloudflare resources and external services. They provide zero-latency access to storage, databases, queues, and other services.

Storage Bindings

KV (Key-Value Storage)

Global, low-latency, eventually consistent key-value storage.

Best for:

  • Configuration data
  • User sessions
  • Cache
  • Small objects (<25 MB)

Configuration:

[[kv_namespaces]]
binding = "MY_KV"
id = "your-namespace-id"
preview_id = "preview-namespace-id"  # For local dev

API:

// Write
await env.MY_KV.put("key", "value");
await env.MY_KV.put("key", "value", {
  expirationTtl: 3600,  // Expire in 1 hour
  metadata: { user: "123" }
});

// Read
const value = await env.MY_KV.get("key");
const json = await env.MY_KV.get("key", "json");
const buffer = await env.MY_KV.get("key", "arrayBuffer");

// With metadata
const { value, metadata } = await env.MY_KV.getWithMetadata("key");

// Delete
await env.MY_KV.delete("key");

// List keys
const keys = await env.MY_KV.list({ prefix: "user:" });

Limits:

  • Key size: 512 bytes
  • Value size: 25 MB
  • Write rate: 1 write/second per key (eventually consistent)
  • Read rate: unlimited

D1 (SQL Database)

Serverless SQLite database built on SQLite.

Best for:

  • Structured data
  • Relational data
  • Complex queries
  • ACID transactions

Configuration:

[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "your-database-id"

API:

// Query with bind parameters
const result = await env.DB.prepare(
  "SELECT * FROM users WHERE id = ?"
).bind(userId).all();

// Insert
await env.DB.prepare(
  "INSERT INTO users (name, email) VALUES (?, ?)"
).bind(name, email).run();

// Update
await env.DB.prepare(
  "UPDATE users SET last_login = ? WHERE id = ?"
).bind(new Date().toISOString(), userId).run();

// Transaction
const results = await env.DB.batch([
  env.DB.prepare("INSERT INTO users (name) VALUES (?)").bind("Alice"),
  env.DB.prepare("INSERT INTO users (name) VALUES (?)").bind("Bob"),
]);

// First row only
const user = await env.DB.prepare(
  "SELECT * FROM users WHERE id = ?"
).bind(userId).first();

Features:

  • Read replication (low latency reads globally)
  • Time Travel (restore to any point in last 30 days)
  • Backups
  • Migrations via Wrangler

Limits:

  • Database size: 10 GB (Paid), 500 MB (Free)
  • Rows read: 25M/day (Paid), 5M/day (Free)
  • Rows written: 50M/day (Paid), 100K/day (Free)

R2 (Object Storage)

S3-compatible object storage with zero egress fees.

Best for:

  • Large files
  • Media storage
  • Static assets
  • Backups

Configuration:

[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "my-bucket"
jurisdiction = "eu"  # Optional: eu or fedramp

API:

// Put object
await env.MY_BUCKET.put("file.txt", "contents", {
  httpMetadata: {
    contentType: "text/plain",
    cacheControl: "max-age=3600",
  },
  customMetadata: {
    user: "123",
  },
});

// Put from stream
await env.MY_BUCKET.put("large-file.bin", request.body);

// Get object
const object = await env.MY_BUCKET.get("file.txt");
if (object) {
  const text = await object.text();
  const buffer = await object.arrayBuffer();
  const stream = object.body; // ReadableStream

  // Metadata
  console.log(object.httpMetadata);
  console.log(object.customMetadata);
}

// Get with range
const object = await env.MY_BUCKET.get("file.txt", {
  range: { offset: 0, length: 1024 }
});

// Head (metadata only)
const object = await env.MY_BUCKET.head("file.txt");

// Delete
await env.MY_BUCKET.delete("file.txt");

// List objects
const objects = await env.MY_BUCKET.list({
  prefix: "images/",
  limit: 1000,
});

// Multipart upload (for large files)
const upload = await env.MY_BUCKET.createMultipartUpload("large.bin");
const part = await upload.uploadPart(1, data);
await upload.complete([part]);

Features:

  • Automatic multipart uploads
  • Object versioning
  • Event notifications
  • Public buckets
  • Custom domains

Limits:

  • Max object size: 5 TB
  • Storage: unlimited
  • Operations: unlimited

Compute Bindings

Durable Objects

Strongly consistent, coordinated stateful objects with SQLite storage.

Best for:

  • Real-time collaboration
  • WebSocket servers
  • Coordination
  • Strong consistency
  • Per-user/per-room state

Configuration:

[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"
script_name = "my-worker"  # Optional: if in different Worker

[[migrations]]
tag = "v1"
new_classes = ["Counter"]

Durable Object Class:

export class Counter {
  state: DurableObjectState;

  constructor(state: DurableObjectState, env: Env) {
    this.state = state;
  }

  async fetch(request: Request): Promise<Response> {
    // Get from storage
    let count = (await this.state.storage.get("count")) || 0;

    // Increment
    count++;

    // Put to storage
    await this.state.storage.put("count", count);

    return Response.json({ count });
  }

  // Alarms (scheduled actions)
  async alarm() {
    await this.state.storage.delete("count");
  }
}

Worker Usage:

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // Get Durable Object ID
    const id = env.COUNTER.idFromName("global-counter");

    // Get stub (reference)
    const stub = env.COUNTER.get(id);

    // Call via fetch
    return stub.fetch(request);
  },
};

Storage API:

// Single operations
await this.state.storage.put("key", "value");
const value = await this.state.storage.get("key");
await this.state.storage.delete("key");

// Batch operations
await this.state.storage.put({
  key1: "value1",
  key2: "value2",
});

const values = await this.state.storage.get(["key1", "key2"]);

// List
const entries = await this.state.storage.list();

// SQL (new)
const result = await this.state.storage.sql.exec(
  "SELECT * FROM users WHERE id = ?", userId
);

Features:

  • SQLite-backed storage
  • Automatic persistence
  • Alarms (scheduled actions)
  • WebSocket Hibernation
  • Point-in-time recovery

Queues

Message queuing for async processing with guaranteed delivery.

Best for:

  • Background jobs
  • Async processing
  • Decoupling services
  • Retry logic

Configuration:

[[queues.producers]]
binding = "MY_QUEUE"
queue = "my-queue"

[[queues.consumers]]
queue = "my-queue"
max_batch_size = 100
max_batch_timeout = 30

Producer (send messages):

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // Send single message
    await env.MY_QUEUE.send({ userId: 123, action: "process" });

    // Send batch
    await env.MY_QUEUE.sendBatch([
      { body: { userId: 123 } },
      { body: { userId: 456 } },
    ]);

    return Response.json({ queued: true });
  },
};

Consumer (receive messages):

export default {
  async queue(batch: MessageBatch<any>, env: Env): Promise<void> {
    for (const message of batch.messages) {
      try {
        await processMessage(message.body);
        message.ack();  // Mark as processed
      } catch (error) {
        message.retry();  // Retry later
      }
    }
  },
};

Features:

  • Guaranteed delivery
  • Automatic retries
  • Dead letter queues
  • Batch processing
  • Pull consumers (API-based)

AI & ML Bindings

Workers AI

Run AI models directly from Workers.

Best for:

  • Text generation (LLMs)
  • Embeddings
  • Image generation
  • Speech recognition
  • Translation

Configuration:

[ai]
binding = "AI"

API:

// Text generation
const response = await env.AI.run("@cf/meta/llama-3-8b-instruct", {
  messages: [
    { role: "system", content: "You are a helpful assistant" },
    { role: "user", content: "What is Cloudflare?" }
  ],
});

// Embeddings
const embeddings = await env.AI.run("@cf/baai/bge-base-en-v1.5", {
  text: "The quick brown fox jumps over the lazy dog",
});

// Image generation
const image = await env.AI.run("@cf/stabilityai/stable-diffusion-xl-base-1.0", {
  prompt: "A sunset over the ocean",
});

// Speech to text
const result = await env.AI.run("@cf/openai/whisper", {
  audio: audioData,
});

// Streaming
const stream = await env.AI.run("@cf/meta/llama-3-8b-instruct", {
  messages: [{ role: "user", content: "Tell me a story" }],
  stream: true,
});

Vectorize

Vector database for similarity search.

Best for:

  • Semantic search
  • RAG (Retrieval Augmented Generation)
  • Recommendations
  • Embeddings storage

Configuration:

[[vectorize]]
binding = "VECTORIZE"
index_name = "my-index"

API:

// Insert vectors
await env.VECTORIZE.insert([
  { id: "1", values: [0.1, 0.2, ...], metadata: { text: "..." } },
  { id: "2", values: [0.3, 0.4, ...], metadata: { text: "..." } },
]);

// Query (similarity search)
const results = await env.VECTORIZE.query(
  [0.15, 0.25, ...],  // Query vector
  {
    topK: 5,
    returnMetadata: true,
  }
);

// With metadata filtering
const results = await env.VECTORIZE.query(vector, {
  topK: 5,
  filter: { category: "technology" },
});

Database Bindings

Hyperdrive

Accelerate access to existing databases via connection pooling and caching.

Best for:

  • Connecting to existing Postgres/MySQL
  • Reducing latency to traditional databases
  • Connection pooling

Configuration:

[[hyperdrive]]
binding = "HYPERDRIVE"
id = "your-hyperdrive-id"

Usage with postgres:

import { Client } from "pg";

const client = new Client({
  connectionString: env.HYPERDRIVE.connectionString,
});

await client.connect();
const result = await client.query("SELECT * FROM users");
await client.end();

Features:

  • Connection pooling
  • Query caching
  • Read replicas support

Service Bindings

Call other Workers via RPC or HTTP.

Configuration:

[[services]]
binding = "AUTH_SERVICE"
service = "auth-worker"
environment = "production"

HTTP-based:

const response = await env.AUTH_SERVICE.fetch(new Request("http://auth/verify"));

RPC-based (recommended):

// In auth-worker
export class AuthService extends WorkerEntrypoint {
  async verifyToken(token: string): Promise<boolean> {
    // Verify logic
    return true;
  }
}

// In calling worker
const isValid = await env.AUTH_SERVICE.verifyToken(token);

Additional Bindings

Analytics Engine

Write custom analytics and metrics.

[[analytics_engine_datasets]]
binding = "ANALYTICS"
env.ANALYTICS.writeDataPoint({
  blobs: ["user-123", "click"],
  doubles: [1.5],
  indexes: ["button-1"],
});

Browser Rendering

Control headless browsers.

browser = { binding = "BROWSER" }
const browser = await puppeteer.launch(env.BROWSER);
const page = await browser.newPage();
await page.goto("https://example.com");
const screenshot = await page.screenshot();

Rate Limiting

Built-in rate limiting.

[[unsafe.bindings]]
name = "RATE_LIMITER"
type = "ratelimit"
namespace_id = "your-namespace-id"
simple = { limit = 100, period = 60 }
const { success } = await env.RATE_LIMITER.limit({ key: userId });
if (!success) {
  return new Response("Rate limited", { status: 429 });
}

mTLS

Present client certificates.

[[mtls_certificates]]
binding = "CERT"
certificate_id = "your-cert-id"
const response = await fetch("https://api.example.com", {
  certificate: env.CERT,
});

Best Practices

Binding Selection

  • KV: Configuration, sessions, cache
  • D1: Structured data, complex queries
  • R2: Large files, media, backups
  • Durable Objects: Real-time, strong consistency, coordination
  • Queues: Background jobs, async processing
  • Workers AI: AI/ML inference
  • Vectorize: Similarity search, RAG

Performance

  • Use ctx.waitUntil() for non-critical writes
  • Batch operations when possible
  • Use appropriate consistency models
  • Cache frequently accessed data

Error Handling

Always handle errors from bindings:

try {
  const value = await env.MY_KV.get("key");
} catch (error) {
  // Handle error
  console.error("KV error:", error);
  return new Response("Service unavailable", { status: 503 });
}

Local Development

Use Wrangler for local testing with bindings:

# KV
wrangler kv:namespace create MY_KV --preview

# D1
wrangler d1 create my-database

# Local dev with bindings
wrangler dev

Additional Resources