Skip to main content

tcb deploy

Read cloudbaserc.json from the project root and roll out functions, static hosting, gateway routes, and database migrations in dependency order, without calling each single-resource command.

v3.8.0+

tcb deploy has supported declarative deployment since v3.8.0. From v3.9.0 it only deploys and never builds, and no longer accepts positional arguments or app-specific options (tcb deploy <serviceName>, --framework, --build-command, --output-dir fail with INVALID_PARAM); use tcb app deploy for cloud builds.

Usage​

tcb deploy [options]

Parameters​

ParameterRequiredDescriptionDefault
-e, --env-id <envId>NoEnvironment ID, highest precedenceenvId in the configuration
--mode <mode>NoApply envOverrides.<mode> and .env.<mode>—
--only <types>NoDeploy only the given resource types, comma-separatedAll
--skip <types>NoSkip the given resource types, comma-separated—
--dry-runNoPrint the change plan without deployingfalse
--yesNoOverwrite existing functions without askingfalse
--concurrency <n>NoConcurrency within a resource type, at most 205
--continue-on-errorNoKeep deploying the other resources after one failsfalse

Valid types for --only / --skip: database / functions / app / hosting / gateway.

Examples​

# Deploy every resource
tcb deploy

# Print the change plan only
tcb deploy --dry-run

# Functions only
tcb deploy --only=functions

# Static hosting and gateway only
tcb deploy --only=hosting,gateway

# Skip the gateway
tcb deploy --skip=gateway

# Skip app and let tcb app deploy build it in the cloud
tcb deploy --skip app

# Specific environment, no overwrite confirmation
tcb deploy --env-id=xxx --yes

# Apply the production overrides
tcb deploy --mode=production

# Three concurrent resources of the same type
tcb deploy --concurrency 3

# Keep going when one resource fails
tcb deploy --continue-on-error

Workflow​

The standard path from zero to production: initialise the configuration, validate it, build locally, preview the changes, then deploy.

StepCommandPurposeDone when
1 Initialisetcb config initDetects functions, frameworks, and static directories, writes cloudbaserc.jsonThe project has a valid configuration
2 Validatetcb validateChecks the schema version, envId, resource directories, and referencesExit code 0 with a resource summary
3 Build locallytcb app buildBuilds app and hosting[] output into their outputDir; only needed for entries with buildCommand, pure static sites can skip itOutput exists in outputDir
4 Previewtcb deploy --dry-runPrints field-level differences (from → to) and the database migration planThe plan matches expectations
5 Deploytcb deployRolls out in database → functions → app → hosting → gateway order, uploading output onlyDeployment succeeds

Options​

--dry-run​

Print the change plan without deploying:

tcb deploy --dry-run

The output covers field-level differences (from → to) and the database migration plan.

--only / --skip​

tcb deploy --only=functions # functions only
tcb deploy --only=hosting,gateway # static hosting and gateway only
tcb deploy --skip=gateway # skip the gateway
tcb deploy --skip app # skip app (pair with tcb app deploy for cloud builds)

Only the five comma-separated resource types are accepted; invalid values fail instead of being ignored:

tcb deploy --only fn # ✗ fn is not a valid resource type
tcb deploy --only "functions hosting" # ✗ space-separated, use commas
tcb deploy --only functions,hosting # ✓

--mode / --env-id​

tcb deploy --mode=production # apply envOverrides.production + .env.production
tcb deploy --env-id=xxx # specific environment (highest precedence)

--concurrency​

Defaults to 5. Instances of the same type deploy in parallel; resource types still run serially in database → functions → app → hosting → gateway order, so dependencies hold.

tcb deploy --concurrency 3 # up to 3 concurrent functions or hosting sites
  • Applies only between consecutive instances of the same type (several hosting sites, several functions); function-to-hosting and hosting-to-gateway transitions always run serially
  • Capped at 20 to avoid overloading the backend API

--continue-on-error​

Default is fail-fast: the first failed resource stops the rest and the process exits non-zero, which CI/CD can detect. --continue-on-error runs every resource first and reports the failures at the end:

tcb deploy --continue-on-error # keep deploying the other resources

database always stops the deployment when it fails, with or without this flag — later resources may depend on the newly created schema.

Behaviour​

Dimensiontcb deploytcb fn deploy / tcb hosting deploy and friends
Configuration sourceOne cloudbaserc.json declares every resourceEach command takes its own arguments
Orchestrationdatabase → functions → app → hosting → gateway, sorted automaticallySingle resource
DependenciesFunctions wait for a new schema (database first), the gateway waits for functions and hostingNot aware
IdempotencyChecks cloud existence, runs on every deployFull run every time
Overwrite confirmationAsks before updating an existing function (--yes skips)--force

Overwrite confirmation: existing functions (update path) ask before being overwritten, --yes skips the prompt, interactive mode confirms item by item, and without any confirmation channel the CLI conservatively skips them instead of overwriting production. The semantics match tcb fn deploy --force.

Build and deploy separation​

tcb deploy deploys only; it never builds or installs dependencies.

ResourceBuild behaviour during tcb deploySince
hosting[]No build, no dependency install, uploads outputDir directlyv3.8.2
appNo cloud build, uploads the output and writes a deployment recordv3.9.0
functions[]Still follows buildStrategy (zip / cloud / local / image)—

When buildCommand is configured but the output directory is missing or empty, the deploy fails with BUILD_OUTPUT_NOT_FOUND and asks you to run tcb app build first:

tcb app build # build app and hosting[] output into their outputDir
tcb deploy # upload the output and roll out the rest

To build a frontend app in the cloud, skip it with --skip app and hand it to tcb app deploy:

tcb deploy --skip app # hosting + functions + gateway, app excluded
tcb app deploy <serviceName> # deploy the app alone with a cloud build

Configuration example​

Minimal cloudbaserc.json:

{
"envId": "your-env-id",
"functions": [
{ "name": "pay-common", "type": "Event", "handler": "index.main" }
],
"hosting": [
{
"name": "web",
"root": "web",
"framework": "vite",
"outputDir": "dist",
"deployPath": "/web"
}
],
"gateway": {
"routes": [
{ "path": "/api", "target": "function:pay-common" },
{ "path": "/web", "target": "hosting:web" }
]
}
}

Matching directory layout:

project/
├── cloudbaserc.json
├── functions/
│ └── pay-common/
│ └── index.js
└── web/
└── dist/ # build output from tcb app build

The full directory convention is in Project layout; database migrations default to cloudbase/migrations/.

Resources​

ResourceFieldKey pointsReference
Database migrationsdatabasepostgresql only; files named 14-digit-timestamp_name.sql in cloudbase/migrations/ by default; a conflict stops the deploymentConfig file - database
FunctionsfunctionsEvent and HTTP types; zip package or image deployment (buildStrategy); HTTP functions support public anonymous access and gatewayPath routingFunction configuration · Deploy functions
Static hosting appappNo build, uploads outputDir and writes a deployment record; outputDir is inferred when missing, pure static sites fall back to the project root; use tcb app deploy for cloud buildsApp deployment
Static hostinghostingMultiple sites as an array; build locally with tcb app build, tcb deploy uploads the output onlyStatic website hosting · tcb app build
Gateway routesgateway.routestarget is function:<name> or hosting:<name>; pathRewrite is generated automaticallyConfig file - gateway
Environment overridesenvOverridesMerged by --modeConfiguration file

A route target: function:<name> accepts both function types: HTTP functions become WEB_SCF routes, Event functions become SCF routes (the gateway wraps the HTTP request into an event). The CLI queries the function detail to decide.

Database migrations​

SQL files in database.migrations are applied to PostgreSQL in order:

DimensionDescription
Supported typetype: postgresql only (type: nosql is passed through, not orchestrated)
Migration filesNamed 14-digit-timestamp_lowercase-name.sql (for example 20260101120000_init.sql), default directory cloudbase/migrations/
Plan (--dry-run)Aggregated into one change item: pending → create
Conflict handlingA migration with the same name already in the target database stops the deployment
Failure policydatabase always stops the deployment, even with --continue-on-error, because later resources may need the new schema

database runs first in the order, so a failure skips every later resource. Confirm the plan with tcb deploy --dry-run first.

Project layout​

Recommended layout:

vibe-app/
├── cloudbaserc.json # declarative configuration (the contract)
├── .env # secrets (not in Git; .env.<mode> with --mode <mode>)
├── .env.example # secret template (in Git)
├── cloudbase/migrations/ # database migrations (SQL, default directory)
│ ├── 20260101120000_init.sql
│ └── 20260102150000_add_users.sql
├── functions/ # function code (functionRoot defaults to ./functions)
│ ├── task-runner/ # Event function: exports.main(event, context)
│ └── api-server/ # HTTP function: needs a scf_bootstrap script
├── web/ # frontend code (hosting[].root)
└── Dockerfile # for HTTP image deployment (optional, inside the function directory)

Path resolution:

ResourceFieldDefault / rule
Migration directorydatabase.migrationscloudbase/migrations/ relative to the project
Function rootfunctionRootfunctions/
Function code directorydir / functionRoot + nameExplicit dir → {cwd}/{dir} (independent of functionRoot); otherwise {cwd}/{functionRoot}/{name}
Frontend sitehosting[].rootRelative to the project directory

FAQ​

1. Which directory is uploaded when app.outputDir is missing?​

tcb deploy does not build; outputDir decides where to upload from, and app follows the same rule as hosting[]:

outputDirResult
A non-empty string ("." counts)Used as-is, no inference
Missing / "" / whitespace onlyInferred: explicit buildCommand → dist; a build command derived from framework or package.json → the framework output directory (falls back to dist); no build command (pure static) → root
Not a string (array, number, …)Fails with INVALID_PARAM

A pure static entry landing on the project root is legal; the terminal prints the actual upload directory and a hint:

[my-app] 上传产物:项目根(/path/to/project)
纯静态站点可保持此配置;前端项目建议用 app.outputDir 指定产物目录(如 dist),并先执行 tcb app build

Frontend projects should set outputDir explicitly, otherwise the sources (including .env) are uploaded as output:

{
"app": {
"serviceName": "my-app",
"outputDir": "dist"
}
}

A missing or empty output directory fails at deploy time with BUILD_OUTPUT_NOT_FOUND; under --dry-run the resource is only marked as not ready.

tcb app deploy resolves differently: --output-dir > app.outputDir > auto-detection > prompt / default (./dist with a build step, ./ without).

2. gateway.routes validation fails (should NOT have additional properties)​

cloudbaserc.json rejects unknown fields. For example cdnType is not a valid route field and must be removed; control CDN access with accessType (DIRECT / CDN / CUSTOM / EO):

{ "path": "/web", "target": "hosting:web", "accessType": "DIRECT" }

3. Dependency installation for HTTP functions​

Function typeRuntimeDependency installation
EventAnyInstalled online in the cloud (default)
HTTPNode.jsInstalled online in the cloud (default)
HTTPNon-Node.js (Python / Php / Java / Go)Must be installed locally and shipped with the code package

For HTTP non-Node.js functions install dependencies locally first (for example pip install into the function directory).

4. Are existing functions overwritten?​

Existing functions ask for confirmation; --yes skips it.

5. Domain-level fields do not apply to routes on an existing domain​

certId / protocol / accessType are domain-level fields shared by every route on the domain. When a route is created on an existing domain these fields do not override the current values (a domain bound to HTTP_AND_HTTPS ignores protocol: "HTTPS"), which protects other services on the same domain. They only take effect when the domain is first created.

6. Gateway route idempotency​

Gateway routes converge idempotently (create / update / skip):

  • Route missing → create
  • Route exists and the explicitly declared fields match → skip
  • Route exists but an explicitly declared field differs → update (calls modifyHttpServiceRoute)

Only explicitly declared fields are compared (enableAuth / enablePathTransmission only when configured, qpsPolicy / pathRewrite only when present locally); undeclared fields never overwrite the cloud configuration. A duplicate path is not an error (unlike the INVALID_PARAM of the imperative tcb routes add). Field definitions: Config file - gateway.