Declarative Deployment (tcb deploy)
tcb deploy declarative orchestration is available since v3.8.0 and requires cloudbaserc.json v2.1.
tcb deploy reads cloudbaserc.json (v2.1) in the project root and orchestrates deployment of cloud functions, cloud apps, static hosting, gateway routes, and database migrations in dependency order — no need to call single-resource commands one by one.
Differences from Single-Resource Commands
| Dimension | tcb deploy | tcb fn deploy / tcb hosting deploy |
|---|---|---|
| Config source | One cloudbaserc.json declares all resources | Each command passes its own arguments |
| Orchestration | database → functions → app → hosting → gateway auto-ordered | Single resource |
| Dependencies | Functions depend on new Schema (database first), gateway depends on functions/hosting | Not aware |
| Idempotency | Cloud existence check + local state snapshot; unchanged resources auto-skip | Full execution every time |
| Overwrite confirmation | Confirms before overwriting existing functions (--yes to proceed) | --force |
Complete Workflow
The standard end-to-end workflow for declarative deployment: Initialize Configuration → validate → preview changes → deploy.
| Step | Command | Purpose | Completion Signal |
|---|---|---|---|
| 1 Initialize config | tcb config init | Auto-detects project resources (cloud function dirs / frontend framework / static hosting dirs) and interactively generates cloudbaserc.json (v2.1) | Valid config created in the project root |
| 2 Validate before deploy | tcb validate | Validates schema version / envId / resource dirs / reference consistency | Exit code 0, resource overview printed |
| 3 Preview changes | tcb deploy --dry-run | Outputs the resource-level change plan: field-level diffs (from → to), hosting file diffs — no actual deployment | Change plan matches expectations |
| 4 Deploy | tcb deploy | Orchestrates deployment in database → functions → app → hosting → gateway order | Deployment succeeds, state snapshot generated |
Quick Start
With cloudbaserc.json already created, run in the project root:
# Validate before deploy (recommended)
tcb validate
# Preview the change plan (no actual deployment)
tcb deploy --dry-run
# Deploy
tcb deploy
cloudbaserc.json found?If no config file exists, tcb deploy warns you about the missing file and guides you to run tcb config init to generate a declarative config template (cloud functions / static hosting / gateway one-click orchestration). It then continues with the traditional cloud app deployment flow, so existing behavior is unaffected.
tcb init vs tcb config inittcb config init(recommended): auto-detects and generates a v2.1 declarative config — the first step of the complete workflowtcb init: legacy template init command (deprecated, usetcb new <appName> [template]instead); generates a v2.0 config, which does not apply to declarative deployment (v2.1)
Minimal cloudbaserc.json (v2.1):
{
"envId": "your-env-id",
"version": "2.1",
"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" }
]
}
}
Corresponding project structure:
project/
├── cloudbaserc.json
├── functions/
│ └── pay-common/
│ └── index.js
└── web/
└─ ─ dist/ # build output (or let tcb deploy build locally)
See Project Directory Convention below for the full layout. Database migrations default to cloudbase/migrations/.
Deployment Flow
tcb deploy orchestrates in the following order (dependencies first):
database → functions → app → hosting → gateway
Overwrite Confirmation
- Functions that already exist in the cloud (update scenario) are confirmed before overwriting
--yesproceeds directly; interactive mode confirms item by item- When no confirmation mechanism is provided, it conservatively skips (never overwrites production without consent)
Incremental Deployment
- After the first successful deployment, a local
.cloudbase/state.jsonfingerprint snapshot is generated - On subsequent deploys: hosting files with identical fingerprints and unchanged app configs are automatically skipped (no re-upload/re-build)
--refreshforces re-comparison against the cloud (drift detection)
Command Options
--dry-run
Outputs only the change plan (terraform plan mindset), without deploying:
tcb deploy --dry-run
Shows field-level changes (from → to), hosting file diffs, and database migration plans.
--only / --skip
Deploy only specified types / skip specified types:
tcb deploy --only=functions # deploy cloud functions only
tcb deploy --only=hosting,gateway # deploy hosting and gateway only
tcb deploy --skip=gateway # skip gateway
Available types: database / functions / app / hosting / gateway.
--mode / --env-id
Apply environment-specific configuration:
tcb deploy --mode=production # apply envOverrides.production + .env.production
tcb deploy --env-id=xxx # specify environment (highest priority)
--refresh
Ignore local state snapshot skip decisions and force re-comparison against the cloud (drift detection):
tcb deploy --refresh
--yes
Proceed with function overwrite updates directly (CI / AI Agent scenarios):
tcb deploy --yes
Concurrency (--concurrency)
Default 1 (strictly serial), consistent with historical behavior. When set, multiple resource instances of the same type are deployed in parallel; cross-type resources still follow the dependency order (database → functions → app → hosting → gateway) serially, without breaking dependencies.
tcb deploy --concurrency 3 # parallelize across functions/hosting sites, max 3 at a time
- Applies only to "consecutive instances of the same type" (e.g., multiple hosting sites, multiple functions); functions vs hosting, hosting vs gateway always run serially.
- Concurrency is capped at
20to avoid excessive pressure on backend APIs.
Failure Interruption (--continue-on-error)
Default is fail-fast: if any resource fails to deploy, subsequent resources are interrupted and the process exits with a non-zero exit code (for CI/CD awareness). To "run through everything and view the failure count at the end", add --continue-on-error:
tcb deploy --continue-on-error # continue deploying the rest even if one resource fails
Exception:
databasefailures always force interruption (regardless of--continue-on-error), because subsequent resources may depend on the newly created database schema.
Resource Configuration Overview
See the corresponding docs for full field details:
| Resource | Config field | Key notes | Docs |
|---|---|---|---|
| Database migrations | database | postgresql only; migration files 14-digit-timestamp_name.sql, default dir cloudbase/migrations/; conflicts abort deployment | PostgreSQL Management |
| Cloud functions | functions | Event / HTTP types; zip code or image deployment (buildStrategy); HTTP functions support public anonymous access and gatewayPath gateway routing | Function Configs · Deploying Functions |
| Cloud app | app | Build path decided by framework: static direct upload / others cloud build | Application Deployment |
| Static hosting | hosting | Array of multiple sites; local build (install + build) then upload | Static Website Hosting |
| Gateway routes | gateway.routes | target: function:<name> / hosting:<name>; pathRewrite auto-generated | Configuration File - Gateway |
| Environment overrides | envOverrides | Merged by --mode | Config File |
The gateway route target: function:<name> supports two function types:
- HTTP type (
type: "HTTP") → created as aWEB_SCFroute - Event type (regular function) → created as an
SCFroute (verified to work; the gateway wraps the HTTP request as an event and forwards it to the function)
The CLI automatically queries function details to determine the type; both types can serve as gateway targets.
Project Directory Convention
Recommended layout (using vibe-app as an example):
vibe-app/
├── cloudbaserc.json # declarative config (core contract, envId/version 2.1)
├── .env # secrets (not in Git; reads .env.<mode> when --mode <mode>)
├── .env.example # secrets template (in Git)
├── cloudbase/migrations/ # database migrations (SQL, default dir)
│ ├── 20260101120000_init.sql
│ └── 20260102150000_add_users.sql
├── functions/ # cloud function code (functionRoot defaults to ./functions)
│ ├── task-runner/ # Event function: exports.main(event, context)
│ └── api-server/ # HTTP function: requires scf_bootstrap
├── web/ # frontend code (pointed by hosting[].root)
└── Dockerfile # optional, for image deployment (inside function dir)
Path resolution rules:
| Resource | Config field | Default / resolution |
|---|---|---|
| Database migration dir | database.migrations | cloudbase/migrations/ (relative to project root) |
| Function root | functionRoot | functions/ |
| Function code dir | dir / functionRoot+name | Explicit dir → {cwd}/{dir} (independent of functionRoot); otherwise {cwd}/{functionRoot}/{name} |
| Frontend site | hosting[].root | Directory relative to cloudbaserc |
FAQ
1. gateway.routes validation failure (should NOT have additional properties)
Schema v2.1 does not allow extra fields. For example, cdnType is not a valid route field — remove it; use accessType (DIRECT / CDN / CUSTOM / EO) to control CDN access:
{ "path": "/web", "target": "hosting:web", "accessType": "DIRECT" }
2. HTTP function dependency installation rules
| Function type | Runtime | Dependency installation |
|---|---|---|
| Event | Any | Cloud-side install (default) |
| HTTP | Node.js | Cloud-side install (default) |
| HTTP | Non-Node.js (Python/Php/Java/Go) | Must install locally and upload with the code |
For HTTP non-Node.js functions, ensure dependencies are installed locally (e.g., Python pip install into the function directory).
3. Will existing functions be overwritten?
Functions that already exist (update scenario) require confirmation by default; --yes proceeds. Declarative deployment semantics align with tcb fn deploy --force.
4. Domain-level fields do not take effect on already-bound domains
certId / protocol / accessType are domain-level fields (shared by all routes under the same domain). When creating routes on an already-existing domain, these fields do not override the domain's original values (e.g. if the domain is already bound with HTTP_AND_HTTPS, setting protocol: "HTTPS" has no effect) — this is the platform's safety behavior to avoid affecting other business routes under the same domain. They only take effect when the domain is first created.
5. Gateway route idempotency semantics
tcb deploy gateway routes converge idempotently (create / update / skip):
- Route does not exist → create (
create) - Route exists and the explicitly declared fields match → skip (
skip) - Route exists but explicitly declared fields differ → update (
update, callsmodifyHttpServiceRoute)
Only explicitly declared fields are compared (enableAuth / enablePathTransmission are compared only when explicitly configured; qpsPolicy / pathRewrite are compared only when the local value is present), and undeclared fields do not override the cloud configuration. Duplicate paths are not treated as errors (unlike the INVALID_PARAM of imperative tcb routes add). See Configuration File - Gateway for the authoritative field definitions.