Guides

Cloudflare Workers

Run City directly on Cloudflare Workers and D1 with @downcity/city, without waiting for a separate edge package.

If you want to deploy Downcity on Cloudflare Workers, the recommended path is not a separate edge package. Wire @downcity/city directly into the Workers runtime.

The public repository includes templates/edge as a developer starter. Downcity's private official Worker implementation lives outside the public repository.

What this path actually solves

The main difference from Node.js is not the HTTP entry. It is the runtime resource model:

  • the database usually comes from a binding such as env.DB
  • environment values are not just a local .env file
  • the request origin may need to be synchronized into services on every request
  • Worker isolates are reused, so runtime cache behavior must be managed explicitly

That is why this is better explained as a guide than as an empty npm package.

The minimum shape

City only needs a Drizzle db object:

import { Federation } from "@downcity/city";
import { drizzle } from "drizzle-orm/d1";

export interface Env {
  DB: D1Database;
}

export default {
  async fetch(request: Request, env: Env) {
    const db = drizzle(env.DB);
    const base = new Federation({ db });

    await base.health();
    return base.handleRequest(request);
  },
};

The important part is not a helper name. It is that you hand the database to City:

  • D1 becomes a db through drizzle-orm/d1
  • D1 is a SQLite dialect, so pass dialect: "sqlite"
  • raw: env.DB is available to services that need the low-level D1 object
  • the current request origin can be synchronized before calls that need OAuth callback URLs

Use templates/edge as a starter

The starter implementation in templates/edge/src/index.ts covers the integration details most projects need:

  • wrap env.DB with drizzle-orm/d1
  • let City initialize the built-in env and cities tables
  • synchronize the current origin before each request so OAuth callbacks and links use the correct domain
  • keep registering AIService, accounts, usage, and payment services the same way as the Node path

For a real project, start from that example and adapt the model catalog, services, and provider keys to your product.

Boundary with the Node path

Worker and Node now use the same mental model: create a Drizzle db, then pass it to new Federation({ db }).

  • Node.js local projects commonly use drizzle-orm/better-sqlite3
  • Node.js production deployments can use Drizzle pg
  • Workers / D1 use drizzle-orm/d1

Next