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
| Mode | Command | Docker required |
|---|---|---|
| Deploy to Cloudflare button | click the button | No |
| CLI, uncached | bun run deploy | No |
| CLI, cached | bun run deploy --cached | Yes, running locally |
| CLI, explicit image | bun 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 deploywrangler 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'sversionwrangler.jsonc'scontainers[].imageandvars.TASUKU_RUNTIME_IMAGEruntime/Dockerfile.cloudflare'sFROMlineruntime/deploy/docker-compose.external.yml'simageruntime/src/version.ts'sRUNTIME_VERSION(generated -- runbun run --filter @tasuku/runtime generate:versionafter bumpingruntime/package.json)
bun run check:pinscheck: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_instancesinwrangler.jsonc'scontainers[]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, andTASUKU_GLOBAL_MAX_RUNNINGare application-level lane limits enforced by theSchedulerDurable 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 --remoteor, 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.