Tasuku
Operations

Deployment

Deploy modes, upgrades, rollback, container image pinning, and concurrency limits.

Tasuku deploys as one Cloudflare Worker. There is no separate server/worker split and no host to patch — wrangler deploy (directly, or through bun run deploy) is the whole deployment.

Deploy modes

ModeCommandDocker required
Deploy to Cloudflare buttonclick the buttonNo
CLI, uncachedbun run deployNo
CLI, cachedbun run deploy --cachedYes, running locally
CLI, explicit imagebun run deploy --image=<ref>No

All four deploy against the prebuilt docker.io/amalshaji/tasuku-agent-runtime:<pin> runtime image unless --cached or --image overrides it. See Install Tasuku for the full walkthrough of each path.

Upgrading

git pull
bun run deploy

wrangler deploy publishes a new Worker version and applies any new D1 migrations on the first request that follows (see below). There is no separate migration step to run first.

Rollback

Cloudflare Workers keeps every deployed version. Use wrangler to roll back the Worker code:

bunx wrangler deployments list
bunx wrangler rollback [deployment-id]

Rollback reverts the Worker's code and configuration; it does not reverse D1 migrations. Because migrations are append-only and additive, a rolled-back older Worker version generally still runs correctly against a newer schema — avoid rollback only when a migration removed a column or table the older version reads.

Container image pinning

The runtime image tag is pinned in five places, and they must agree:

  • runtime/package.json's version
  • wrangler.jsonc's containers[].image and vars.TASUKU_RUNTIME_IMAGE
  • runtime/Dockerfile.cloudflare's FROM line
  • runtime/deploy/docker-compose.external.yml's image
  • runtime/src/version.ts's RUNTIME_VERSION (generated -- run bun run --filter @tasuku/runtime generate:version after bumping runtime/package.json)
bun run check:pins

check:pins (part of bun run check) fails with a diff if any of the five disagree. Bump all five together when releasing a new runtime image.

Concurrency limits

Two different mechanisms bound how many agent runs execute at once, and they are independent:

  • max_instances in wrangler.jsonc's containers[] caps how many container instances Cloudflare will run per class (standard-2: 3 by default, standard-4: 1 by default). This is an account/plan-level ceiling — raising it may require a higher Cloudflare container quota.
  • TASUKU_MAX_CONCURRENT_AGENTS, TASUKU_MAX_CONCURRENT_REVIEWS, and TASUKU_GLOBAL_MAX_RUNNING are application-level lane limits enforced by the Scheduler Durable Object — the same two-lane design (agent work vs. reviews) the Go worker used, now backed by in-memory counts in a single-threaded DO instead of a Postgres advisory lock.

Keep the application-level limits at or below what max_instances (and any Daytona/external-runtime capacity) can actually satisfy; a limit the sandbox provider can't back just means work queues without a working attempt ever claiming it. See Environment variables for defaults and Sandbox providers for provider capacity.

Custom domains

Add a custom domain the same way as any Cloudflare Worker — a route or a workers.dev alternative bound in the dashboard, or a routes/custom_domains entry in wrangler.jsonc. The instance's public URL is captured once, permanently, from the bootstrap request's Origin header (falling back to TASUKU_PUBLIC_URL only if that header isn't usable) — there is currently no supported way to change it after bootstrap, so plan the custom domain (or set TASUKU_PUBLIC_URL to it) before bootstrapping if webhook and OAuth callback URLs need to match it from the start; see Public URL.

D1 migrations

Migrations are self-applying: the Migrator Durable Object applies every pending server/drizzle/*.sql file transactionally, one file per D1Database#batch() call, the first time any request reaches an /api/* route or /readyz after a deploy (both run behind the same migrations-gate middleware — server/src/app.ts:122-123), and at the start of every Workflow — no separate migration command is required for a normal upgrade.

To apply migrations without traffic reaching the Worker (for example, to warm a fresh D1 database before pointing DNS at it), use wrangler directly:

wrangler d1 migrations apply tasuku --remote

or, for local development, bun run db:migrate (wrangler d1 migrations apply tasuku --local). wrangler d1 migrations apply and the Migrator DO write to the same d1_migrations bookkeeping table, so either one can run first without conflicting with the other.

On this page