Skip to content

Naming Conventions

How Tamer derives Cloudflare names from your config, and how to override them for brownfield stacks where the legacy names don't follow the default pattern.

Default name patterns

When no naming hook or per-resource cloudflareName override is set, Tamer derives Cloudflare names from the logical name + env. The stack identity is available to hooks but is not embedded in the defaults (except worker script names and shard-group physical names, which include the stack/product).

ResourceDefault name
D1 singledb_{logical}_{env}
D1 shardeddb_{logical}_{YYYYMMDD}_{env}
R2 bucketr2-{logical}-{env}
KV namespacekv_{logical}_{env}
Queueq-{logical}-{env}
Hyperdrivehd-{logical}-{env}
Vectorizevec-{logical}-{env}
AI Gatewayaigw-{logical}-{env}
Pipelinepipe-{logical}-{env}
Workflowwf-{logical}-{env}
Secrets Storesec-{logical}-{env}
Worker script{stack}-{workerKey}-{env} (local omits -{env})
Dispatch namespace{product}-{env} (from wfp.namespaces)
Tenant dispatch script{service}-{workspace}-{env}
Shard group physical (stack)db_{group}_{NNN}_{stack}_{env} → binding {prefix}_{NNN}
Shard group physical (tenant)db_{group}_{NNN}_{product}_{workspace}_{env} → binding {prefix}_{NNN}
Per-tenant utility D1db_{logicalName}_{product}_{workspace}_{env}

logicalName is stable stack identity — used for state keys and ${tamer:…} references regardless of how the Cloudflare-side name is computed. Cloudflare IDs (UUIDs, etc.) are never in config; they land in state after sync / apply.

Overriding names

Three layers, applied in this resolution order:

  1. Per-resource cloudflareName — set on an individual resource config to override just that one resource's name.
  2. Stack naming hooksnaming: { d1Single, d1Shard, r2Bucket, workerName, workflow } — one formula for every resource of a kind.
  3. NamingEngine default — the table above (greenfield).

Stack naming hooks (greenfield + shared patterns)

Declare on the root defineConfig({ … }). Each hook receives the stack identity as a parameter so custom formulas can still embed it.

HookUsed forDefault when omitted
d1Singled1 resources with type: "single"db_{logical}_{env}
d1Shardd1 resources with type: "sharded"db_{logical}_{YYYYMMDD}_{env}
r2BucketR2 bucketsr2-{logical}-{env} (date arg is YYYYMMDD at apply time; ignore if unused)
workerNameDeployed Worker script names{stack}-{workerKey}-{env} (or scriptName override)
workflowWorkflow registration nameswf-{logical}-{env} (lowercase)

Not configurable via naming today: KV, queues, hyperdrive, vectorize, pipelines, AI gateway, secrets store, dispatch namespaces, DNS. Those use built-in derived names.

API details (defaults, date parameter, sync matching): JSDoc on NamingConventions from @dragonmastery/tamer (source in src/types.ts).

Per-resource cloudflareName (brownfield)

When legacy Cloudflare names differ per logical resource rather than following one formula, set optional cloudflareName on each resource config instead of (or in addition to) stack naming.*:

ts
workflows: [
  {
    logicalName: "referral-event",
    className: "ReferralEventWorkflow",
    cloudflareName: (stack, env) =>
      env === "dev"
        ? "referral-event-workflow-dev"
        : `${stack}-app-saai-referral-event-workflow-${env}`,
  },
],

cloudflareName receives (stack, env, ctx?) where ctx.shardDate is passed for sharded D1. Workers use scriptName (no cloudflareName).

Brownfield adoption

Existing Cloudflare resources keep their Cloudflare names — reproduce those patterns via naming hooks and/or per-resource cloudflareName. Then run bootstrapsyncplanapply. sync adopts resources whose Cloudflare name equals the derived name.

ts
export default defineConfig({
  stack: "acme",
  compatibility_date: "2025-12-01",
  naming: {
    d1Single: (logical, _stack, env) => `acme-${logical}-${env}`,
    r2Bucket: (logical, _date, _stack, env) => `acme-${logical}-${env}`,
    workerName: (stack, workerKey, env) => `${stack}-${workerKey}-${env}`,
    workflow: (logical, _stack, env) => `acme-${logical}-${env}`,
  },
  workers: { /* … */ },
});

See Brownfield Adoption for the full sync/import flow and tamer import escape hatch.

  • Brownfield Adoption — sync/import flow, escape hatch
  • Config Types — full type reference
  • JSDoc on NamingConventions and CloudflareNameFn from @dragonmastery/tamer

Released under the Tamer Evaluation License.