Branching
Branching is currently in Private Alpha:
- The feature is under active development and available to invited users only. Access must be requested.
- APIs, parameters and response fields may change in incompatible ways before general availability.
- No SLA is provided. Do not use it in production workloads.
To request access or send feedback, contact your account manager or submit a ticket.
Branching lets you manage your backend the way you manage code: create a branch from an environment, and the branch comes with the full database schema, RLS policies and data as a fully isolated environment. You can change tables, write data and deploy functions on the branch, or let an AI agent do it, without affecting the main environment.
A single CreateBranch call gives you a working branch environment, plus an ephemeral key that can only access that branch.
Use with an AI agent
Click "Copy page" or "View Markdown" on the right side of this page and give the content to your agent (Claude Code, Cursor, CodeBuddy, etc.), or send it the link to this page.
Make sure the agent's runtime has the environment variables from Prerequisites, then give it an instruction such as:
Read https://docs.cloudbase.net/en/database/postgresql/branching,
use the Tencent Cloud credentials in the environment variables to create a branch named feat-login from main,
then add a phone column to the users table on the branch.
Use cases
- A safe workspace for AI agents: the agent creates tables, changes RLS and writes test data on the branch. The branch's ephemeral key cannot access main, so the agent never touches production data.
- Validate on real data before release: the branch carries main's full data, so new features, new queries and performance issues surface on near-production data.
- Rehearse destructive migrations: before dropping columns, changing types or rebuilding indexes, run them on a branch first to check duration and results.
- One environment per task: when developing several features in parallel, each feature gets its own branch without interfering with the others.
How it works
A branch is an independent CloudBase environment with its own environment ID (BranchId), database, functions and endpoints. It also records its parent branch, forming a branch tree. The root environment itself is main (Depth 0).
When a branch is created, the platform copies the parent branch's content into the new environment:
| Resource | State in the branch |
|---|---|
| PostgreSQL | Full copy: schema, indexes, RLS policies, functions and data. The branch database is separate; reads and writes do not affect each other |
| Authentication | Authentication config is inherited along with the database |
| Cloud functions | Copied |
| API keys | Not copied. An ephemeral key for the branch is returned on creation; see Branch ephemeral key |
A branch has the same specification as its parent. Branches can have child branches, up to 5 levels deep.
Prerequisites
- Access: a Tencent Cloud account with Private Alpha access, and a CloudBase environment under a platform edition that uses PostgreSQL (shared instance).
- A dedicated CAM sub-account: create a sub-account in the CAM console, grant it only CloudBase (
tcb) permissions, and create an API key (SecretId / SecretKey) for it. Do not use the root account's key. - Configure the key as environment variables in the environment that runs your scripts or agent (for example, shell profile,
.envfile or CI secrets):
export TENCENTCLOUD_SECRET_ID=<sub-account SecretId>
export TENCENTCLOUD_SECRET_KEY=<sub-account SecretKey>
export ENV_ID=<your environment ID>
⚠️ Note: keep the key in environment variables only and do not paste it into an agent conversation. The agent only needs the variable names; the SDK reads them and signs requests at runtime.
- Install the SDK (Node.js 18+):
npm install tencentcloud-sdk-nodejs-common
Quick start
The examples below use the common client of the Tencent Cloud Node.js SDK to call the CloudBase tcb service (version 2018-06-08).
Step 1: Create a branch
// create-branch.js
const { CommonClient } = require("tencentcloud-sdk-nodejs-common");
const client = new CommonClient("tcb.tencentcloudapi.com", "2018-06-08", {
credential: {
secretId: process.env.TENCENTCLOUD_SECRET_ID,
secretKey: process.env.TENCENTCLOUD_SECRET_KEY,
},
region: "ap-shanghai",
});
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function main() {
const envId = process.env.ENV_ID;
// 1. Create a branch from main (the root environment itself)
const res = await client.request("CreateBranch", {
EnvId: envId,
BranchSetting: { ParentBranchId: envId, BranchName: process.env.BRANCH_NAME },
});
const branchId = res.BranchId;
console.log("BranchId:", branchId);
// 2. Poll until ready: Status 1 = creating, 0 = ready
while (true) {
await sleep(10_000);
const { BranchList } = await client.request("DescribeBranchList", { EnvId: envId, BranchId: branchId });
if (BranchList[0].Status !== 1) {
console.log("Status:", BranchList[0].Status, BranchList[0].FailReason || "ready");
break;
}
}
}
main();
BRANCH_NAME=feat-a node create-branch.js
CreateBranch returns the BranchId immediately and the branch enters the creating state (Status = 1). Poll DescribeBranchList; the branch is ready when Status becomes 0. If creation fails, FailReason gives the reason. The ApiKey in the response is the branch ephemeral key; see Branch ephemeral key.
Step 2: View the branch tree
const res = await client.request("DescribeBranchList", { EnvId: process.env.ENV_ID });
for (const b of res.BranchList) {
console.log(`${" ".repeat(b.Depth)}${b.BranchName} ${b.BranchId} status=${b.Status}`);
}
main my-app-xxxx status=0
feat-a feat-a-xxxx status=0
Step 3: Work on the branch
A branch is a regular environment, so any tool that accepts an environment ID works with the BranchId:
tcb fn deploy hello -e <BranchId>
tcb db execute -e <BranchId> --sql "ALTER TABLE notes ADD COLUMN title text"
You can also use the branch ephemeral key to call the branch's data API directly:
# Read: returns the data in the branch (copied from main)
curl -s "https://<BranchId>.api.tcloudbasegateway.com/v1/rdb/rest/notes?select=id,body" \
-H "Authorization: Bearer $BRANCH_KEY"
# Write: goes to the branch only; main is not affected
curl -s -X POST "https://<BranchId>.api.tcloudbasegateway.com/v1/rdb/rest/notes" \
-H "Authorization: Bearer $BRANCH_KEY" -H "Content-Type: application/json" \
-d '{"body": "written on branch"}'
Using the same key against main returns 401 INVALID_CREDENTIALS.
Step 4: Delete the branch
await client.request("DeleteBranch", {
EnvId: process.env.ENV_ID,
BranchId: "<BranchId>",
});
After deletion, the branch is removed from the list immediately and its environment resources are reclaimed automatically. A branch with child branches cannot be deleted until its children are deleted.
Branch ephemeral key
The CreateBranch response includes a server-side key dedicated to the branch (KeyType is ephemeral_secret, prefixed with cb_secret_):
- Valid for 1 hour and expires automatically.
- Only works for this branch; using it on main or another branch returns
401. - Acts as the branch's administrator and bypasses RLS. Use it only on servers or in the agent's runtime, never in frontend code.
For tasks expected to take longer than 1 hour, the developer can call CreateApiKey for the branch with their own CAM identity to create a long-lived key and write it straight into an environment file, instead of having the agent create it or pasting it into the conversation:
tccli tcb CreateApiKey --EnvId <BranchId> --KeyType api_key --KeyName agent-dev \
--region ap-shanghai | jq -r '.ApiKey' > .cloudbase-branch.key
chmod 600 .cloudbase-branch.key
API reference
All three APIs belong to the CloudBase tcb service, version 2018-06-08, endpoint tcb.tencentcloudapi.com, signed with TC3-HMAC-SHA256.
CreateBranch
Creates a new branch from the specified parent branch.
Request parameters
| Name | Type | Required | Description |
|---|---|---|---|
| EnvId | String | Yes | Root environment ID |
| BranchSetting.ParentBranchId | String | Yes | Parent branch ID. Use the root environment ID to branch from main |
| BranchSetting.BranchName | String | Yes | Branch name, used as the prefix of the BranchId |
| ReqKey | String | No | Request identifier |
Response parameters
| Name | Type | Description |
|---|---|---|
| BranchId | String | New branch ID, which is also the branch's environment ID |
| BranchInfo | Object | Branch information; same fields as DescribeBranchList |
| ApiKey | Object | Branch ephemeral key: ApiKey (key value), KeyType (ephemeral_secret), expiry time |
DescribeBranchList
Lists the branches of an environment.
Request parameters
| Name | Type | Required | Description |
|---|---|---|---|
| EnvId | String | Yes | Root environment ID |
| BranchId | String | No | Query only the specified branch |
| Depth | Integer | No | Filter by level, 0–5; 0 is main |
| Offset | Integer | No | Pagination offset |
| Limit | Integer | No | Page size |
Response parameters
| Name | Type | Description |
|---|---|---|
| Total | Integer | Total number of branches (including main) |
| BranchList[].BranchId | String | Branch ID |
| BranchList[].BranchName | String | Branch name; main for the root |
| BranchList[].Depth | Integer | Level; 0 for main |
| BranchList[].ParentBranchId / ParentBranchName | String | Parent branch |
| BranchList[].Status | Integer | 1 creating, 0 ready |
| BranchList[].FailReason | String | Reason for creation failure |
| BranchList[].CreateTime | String | Creation time |
DeleteBranch
Deletes the specified branch. Returns an error if the branch has child branches; delete the children first.
Request parameters
| Name | Type | Required | Description |
|---|---|---|---|
| EnvId | String | Yes | Root environment ID |
| BranchId | String | Yes | ID of the branch to delete |
Limits
- Only environments under a platform edition with a PostgreSQL shared instance are supported. Calls on regular plan environments (Personal, Standard, etc.) return
UnsupportedOperation.BranchOperation. - A branch has the same specification as its parent; each branch counts toward the environment quota.
- After a branch is created, later changes on main are not synced to the branch.
- This version does not provide branch diff, merging back to main, or resetting from the parent branch.
- Creation time depends on the amount of data and the number of functions.