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

# Deployments

> Every save of your API's Worker is an immutable preview deployment with its own URL: test it, deploy it to production or discard it, share it as a pinned version, roll back in seconds.

On the edge gateway every save of an API's Worker creates a **deployment**: an immutable snapshot of the files it runs, the template, the variables and the bindings. Your API's hosts (`{api}.jojapi.net` and your custom hosts) serve the **production** deployment. Every other active deployment has its own URL, so you can test a change before your consumers see it, share an exact version, and go back to a previous one without rebuilding anything.

<Info>
  Deployments exist for APIs served by the edge gateway (the **Worker** tab). Open **Worker → Deployments** in the Studio, or use the [CLI](#cli-and-management-api).
</Info>

## URLs

| URL | Serves |
| - | - |
| `https://{api}.jojapi.net` (and custom hosts) | the production deployment |
| `https://{api}--{id}.jojapi.dev` | one deployment, pinned: it never changes |
| `https://{api}--preview.jojapi.dev` | the latest deployment, promoted or not |

Every URL goes through the same gateway: API keys, subscriptions, plans, quotas, rate limits, billing and request logs work exactly as on production. Calls to a deployment URL are billed like any other call. Each answer carries `x-jojapi-deployment: {id}`, so you always know which version responded.

## Every save is a preview first

Saving never changes production by itself. Every save — the template, your code (browser editor or `jojapi deploy`), **Edit code** / **Back to template**, a variable or secret, a storage binding — updates your saved configuration and creates a **preview** deployment of it. The preview runs at `https://{api}--preview.jojapi.dev` and at its own URL, and it stays there when you reload the page or come back later. A storage binding is added together with the code that uses it and tested on the preview before your consumers get either.

While production runs something older than your saved configuration, a bar on the Worker tab says how many changes production is behind and lists them:

* **Deploy to production** serves the latest preview on your production hosts within seconds, with an optional release note. If the latest preview did not build, the bar shows why; fix the cause and save again.
* **Discard** returns your template, code, variables and bindings to what production runs, and archives the previews made since. Their snapshots stay under Deployments, where you can activate or promote them again.

| Save | Creates | Goes to production |
| - | - | - |
| Template, variable, secret, storage binding, Edit code / Back to template | a preview of your saved configuration | when you deploy it |
| Code in the browser editor, `jojapi deploy` | a preview of your files; an API in template mode switches to code mode | when you deploy it — or at once with **Deploy to production** in the editor or `jojapi deploy --prod` |
| Variable with **Save and deploy** | production's deployment with only this value changed | at once |

**Save and deploy** is for urgent cases such as rotating a leaked key: the new value goes live immediately without your other pending changes, which stay pending in a new preview. Console logging is a Worker setting, not part of a deployment; switching it applies to production and every active deployment at once.

### Removing storage

Removing a storage binding takes it out of the preview; production keeps it until you deploy. The key-value store, database, bucket or queue — and its data — is deleted once no active deployment uses it any more, production and the previous production included, so a rollback still finds it. If the deletion fails (object storage must be empty), the binding shows why and the deletion is tried again after every deploy and daily. Its name can be reused once it is deleted.

## Test a deployment from the playground

On your API's marketplace page, the playground shows you, as the API's owner, a **Send requests to** choice above **Send Request**. Nobody else sees it.

* **Production**: your public host, the one your consumers call (the default).
* **Latest preview**: `https://{api}--preview.jojapi.dev`, the newest deployment.
* **A deployment**: one active deployment, listed with its number, id, branch or pull request and age.

Only the host changes: the path, query, headers and API key stay the same, and **Code Snippets** use the chosen host. Each request in the playground history shows where it ran, for example `Preview · #8 bhsmu1w6`, taken from the `x-jojapi-deployment` header. The choice is kept for the browser tab.

Requests to a deployment are real: your Worker runs, and the gateway bills them like production requests on your own subscription to the API. Quota, balance and rate limits apply, and the requests appear in your usage and request logs. Without a subscription of your own, the gateway answers `401 Subscription Not Found`.

## Promote and roll back

**Promote** serves a deployment on your production hosts within seconds. You can add a **release note**: promotions with a note appear as **Releases** on your API's public page. Every promotion, with or without a note, moves the page's "last updated" date. Consumers never see unpromoted deployments, and a deployment's description stays in your Studio.

**Roll back** returns production to the deployment it served before. A deployment carries its variables and bindings, so rolling back restores their values too — secrets included. If you rotated a leaked key, deploy again after the rollback. Your saved configuration does not change: the rolled-back changes show as pending again until you fix and deploy them, or discard them.

Stateful objects keep one shared state: every deployment of an API talks to the same objects as production. A class that production does not have yet starts with its own empty state in a preview and moves to the shared state when that deployment is promoted.

## Access

Your production hosts always serve every subscriber. The access setting only concerns a deployment's own URL, and it appears on every deployment except the one in production:

* **My keys only** (default): only API keys of your own account can call the URL; anyone else gets `403 Deployment Is Private`.
* **Public URL**: any subscriber of your API can call it, billed as usual. Share it to let a consumer pin an exact version while production moves on.

The `--preview` URL is always for your keys only.

## Active and archived deployments

An **active** deployment is deployed and callable. Three active deployments per API are included in [compute usage](/studio/custom-code#compute-usage); beyond that, each costs the list price of **\$0.02 per deployment per month**, prorated by day. To keep routine saves free, the oldest active deployment is archived automatically once more than three are active — except production, the previous production, the latest deployment, public deployments and those you **Keep active**.

An **archived** deployment keeps its snapshot but no longer runs: its URL answers `410 Deployment Archived` with your production URL. **Activate** brings it back in seconds (and keeps it active); promoting an archived deployment activates it as well. The last 100 deployments of an API are retained. An API can keep up to 50 deployments active; write to support if you need more.

## CLI and Management API

```bash theme={null}
jojapi deploy                  # preview deployment, prints its URL
jojapi deploy --prod           # deploy and promote (without changes: promote the latest)
jojapi deploy --message "Faster search"
jojapi deploy --prod --note "Faster search results"   # production with a public release note
jojapi deployments             # newest first, with production / previous / latest
jojapi promote k3j9x2ab --note "Faster search results"
jojapi rollback
```

To deploy from a GitHub repository — a preview for every pull request, production on every merge — see [Deploy from GitHub](/studio/github-actions).

The same actions are [Management API](/studio/management-api#worker-code-edge-gateway) routes: `provider-api-edge-deployments` (with the pending changes), `deploy-api-edge-changes`, `discard-api-edge-changes`, `promote-api-edge-deployment`, `rollback-api-edge` and `update-api-edge-deployment` (access, Keep active, archive, activate), with the `code:read` and `code:write` scopes. Saves through the API are previews too; `production: true` deploys at once.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.