> ## Documentation Index
> Fetch the complete documentation index at: https://docs.deep.space/llms.txt
> Use this file to discover all available pages before exploring further.

# Deployment

> How DeepSpace deploys your app to Cloudflare Workers for Platforms.

`npx deepspace deploy` builds your app and uploads it to Cloudflare Workers for Platforms, returning a live `<name>.app.space` URL.

## What `deploy` does

The CLI builds your app with Vite (the Cloudflare plugin produces both the client bundle and the worker), validates your binding manifest, and uploads everything to the deploy worker as one request. From there, the platform auto-provisions any binding marked `"auto"`, applies your user secrets from `.dev.vars` as `secret_text` bindings, and registers the worker in the dispatch namespace at `<name>.app.space`.

Deploys are idempotent. Re-running `deploy` with no source changes reuses provisioned resources and uploads unchanged code as a no-op.

See [Build & deploy pipeline](/concepts/architecture#build--deploy-pipeline) for the full step-by-step. Inspect deployed apps, logs, and traffic in the web dashboard at [dashboard.deep.space](https://dashboard.deep.space).

## Subdomains

`<name>.app.space` is a fully production-grade URL with SSL - most apps ship and stay on it. The `name` field in `wrangler.toml` is your subdomain:

```toml theme={null}
name = "my-app"
# → deploys to https://my-app.app.space
```

Rules:

* Lowercase alphanumeric with optional dashes, up to 63 characters; cannot begin with a dash
* Non-conforming names cause the CLI to fail with a clear error and the suggested canonical form; fix `name` in `wrangler.toml` and re-run
* Renaming `name` after deploy and re-deploying gives you a new subdomain - the old one becomes orphaned (still accessible until explicitly undeployed)

If you'd rather use your own domain (e.g. `myapp.com`), see [Custom domains](/guides/custom-domains).

## State preservation

A deploy **does not** wipe Durable Object state. Your records, conversations, files, and cron history persist across deploys.

**Survives a deploy:**

* Durable Object SQLite tables (records, Yjs documents, canvas state, cron history)
* R2 bucket contents
* Auto-provisioned bindings (D1, KV, Vectorize, etc.). Resource IDs are persisted and reused.
* User secrets in `.dev.vars`. Re-uploaded each deploy; same values land as `secret_text` bindings.

**Does not survive a deploy:**

* Worker module-level globals
* In-memory caches inside DOs. Every DO restarts; persistent storage stays, in-memory state is rebuilt on the next request.

### Schema migrations

The SDK runs **additive** schema migrations automatically. When a DO cold-starts after a deploy, the per-collection migrator creates any new tables and runs `ALTER TABLE ADD COLUMN` for new fields. Re-running with an unchanged schema is a no-op.

**Destructive** changes are not handled: dropping a column, changing a column type, renaming a field, or backfilling data into a new shape. You're responsible for any data migration before deploying a breaking schema change.

## Secrets and `.dev.vars`

The CLI writes SDK-managed keys at the top of `.dev.vars`, followed by a divider, followed by anything you've added:

```bash .dev.vars theme={null}
AUTH_JWT_PUBLIC_KEY=...
AUTH_JWT_ISSUER=...
AUTH_WORKER_URL=...
API_WORKER_URL=...
PLATFORM_WORKER_URL=...
OWNER_USER_ID=...
APP_OWNER_JWT=...
APP_IDENTITY_TOKEN=...
ALLOW_DEBUG_ROUTES=...

# --- not managed by the SDK; preserved across dev/test runs ---
STRIPE_SECRET_KEY=sk_test_...
OPENAI_API_KEY=sk-...
MY_FEATURE_FLAG=true
```

Anything **below** the divider:

* Is preserved verbatim across `dev` / `test` / `deploy` runs
* Becomes a `secret_text` binding on deploy (`env.STRIPE_SECRET_KEY` in worker code)
* Never appears in compiled assets or client bundles

<Warning>
  **Never commit `.dev.vars`.** The scaffold's `.gitignore` covers it. To rotate a secret, edit the file and redeploy.
</Warning>

### Secret constraints

| Limit                    | Value                      |
| ------------------------ | -------------------------- |
| Name pattern             | `^[A-Za-z_][A-Za-z0-9_]*$` |
| Per-value size           | 32 KB                      |
| Total across all secrets | 128 KB                     |
| Raw deploy payload       | 1 MB                       |

Size limits are Cloudflare's, enforced on `secret_text` bindings.

Secret names cannot collide with any reserved binding name, custom binding, or Durable Object binding name. The CLI fails locally with a clear error before any upload.

## Custom bindings

Add Vectorize, Workers AI, R2, KV, D1, Queues, Browser Rendering, Hyperdrive, or Analytics Engine bindings by declaring them in `wrangler.toml`. Set the ID to `"auto"` to auto-provision:

```toml theme={null}
[[vectorize]]
binding = "VEC"
index_name = "auto"
dimensions = 768
metric = "cosine"

[[d1_databases]]
binding = "MY_DB"
database_id = "auto"
database_name = "my-app-db"
```

The deploy worker provisions the resource the first time you deploy, persists the ID, and reuses it on every subsequent deploy. See [Custom bindings](/guides/custom-bindings) for the full list of types and gotchas.

## Undeploy

To take an app down:

```bash theme={null}
npx deepspace undeploy
```

This removes the subdomain registration, tears down auto-provisioned resources (with one exception), and cleans up bindings. The exception:

* **R2 buckets with files in them are not auto-deleted.** This protects against accidental user-content loss. Empty the bucket manually if you want it gone.

Durable Object data **is** removed when the worker is undeployed. Back up anything you want to keep.

## Before your first deploy

Three things to verify before shipping:

* **Finalize the app name.** Renaming `name` in `wrangler.toml` later creates a new subdomain and orphans the old one.
* **Audit `.dev.vars`.** Every key below the divider ships as a `secret_text` binding. Confirm prod credentials, not test keys.
* **Run `npx deepspace test`.** Playwright runs your specs against a local build before you deploy them against the live one.

## Next steps

* [Deploy command reference](/cli-reference/commands#deploy) - flags, environment variables, and edge cases.
* [Custom bindings](/guides/custom-bindings) - declare Vectorize, R2, D1, and more.
* [Custom domains](/guides/custom-domains) - optionally buy and attach your own domain from the CLI.
* [Testing](/guides/testing) - run Playwright specs before you ship.
