"Environments"

Every Tether project can have several environments, such as `development`, `staging` and `production`. Each environment is fully isolated: it has its own SQLite database, functions, crons, environment variables, logs, backups, files and API keys.

You manage environments in the dashboard under Settings > Environments. The CLI picks the environment from your API key (a tthr_prod_* key deploys to production), or from -e:

tthr deploy -e staging

Creating environments

Create environment offers Production and Staging presets, or a custom name. Names are up to 32 characters and use lowercase letters, numbers, hyphens and underscores.

You can start empty or clone another environment. Cloning copies schema, functions, crons, row-level security policies and table structure, but never data, environment variables, logs, backups or database tokens.

Promoting between environments

Promotion copies schema and functions from one environment into another, for example from staging to production, without running the CLI against production. Data is never copied.

  1. In Settings > Environments, choose Promote on the environment you want to copy from.
  2. Pick the environment to promote into.
  3. Review the diff. It lists:
    • tables added, removed or changed, with each column that is added, removed or changed (type, required, unique, default, reference, on delete, allowed values)
    • functions added, changed (code, source, arguments, access or type) or removed
    • tables whose row-level security settings or policies differ
  4. Confirm. If the promotion removes any tables, columns or functions, you're asked to type the target environment's name first.

After a promotion the target matches the source:

  • New tables are created and new columns are added.
  • Tables and columns that only exist in the target are removed. As with tthr deploy, anything that still holds data is soft-deleted rather than dropped, so it can be recovered.
  • Functions are replaced with the source's versions, and functions the source doesn't have are removed.
  • Row-level security settings and policies are replaced with the source's.

SQLite can't change an existing column in place, so a changed column updates Tether's column metadata while the constraints already on that column in the target stay as they are. This is the same behaviour as a CLI deploy.

The promotion is recorded in the target environment's deployment history as a promotion deployment, with the full diff. The schema half is also recorded as a regular schema deployment.

If either environment changes between the preview and your confirmation (for example a teammate deploys), the promotion is refused and the dashboard shows the new diff to review.

Promotion API

Promotion needs a signed-in user. Environment API keys can't promote, because a promotion spans two environments. OAuth2 tokens need the deploy scope.

POST /api/v1/projects/{projectId}/env/{source}/promote/preview
Content-Type: application/json

{ "target": "production" }

The response contains diff, hasChanges and a fingerprint. Send the fingerprint back to apply exactly that diff:

POST /api/v1/projects/{projectId}/env/{source}/promote
Content-Type: application/json

{ "target": "production", "fingerprint": "sha256:..." }

A 409 Conflict means the environments changed since the preview.

Restoring a backup into a new environment

You can restore any completed backup into a brand-new environment, so you can inspect old data side by side without touching the environment it came from.

  1. Open Settings > Backups for the environment the backup belongs to.
  2. Choose Restore to new environment on a completed backup.
  3. Name the new environment. Tether suggests one based on the source and the backup date, for example production-20261001.

The new environment gets the backup's data, schema, functions, row-level security policies, logs and deployment history. To keep the copy safely apart from the source:

  • Crons are turned off. Nothing runs on a schedule against old data until you turn a cron back on.
  • Environment variables and database tokens are not restored. They belong to the source environment. Add environment variables to the copy if you need to run its functions.
  • Backup history is not carried over, so deleting or expiring backups in the copy can never remove the source's backups.
  • File records are not carried over. Uploaded files stay with the source environment. Asset IDs stored in your own columns are kept as plain values.

The restore is recorded in the new environment's deployment history as a restore deployment, with the source environment and backup ID. The new environment gets its own API key and starts with automatic backups turned off.

Restore API

OAuth2 tokens need both the backups and settings scopes.

POST /api/v1/projects/{projectId}/env/{source}/backups/{backupId}/restore-to-environment
Content-Type: application/json

{ "name": "production-20261001" }

The response contains the new environment and a restored summary (tables, cronsDisabled, backupsDetached, assetsDetached, envVarsRemoved, dbTokensRemoved).