---
title: "Upgrades and compatibility"
description: "Move a running deployment to a newer Chickpea release without losing state, keys, or resource identities."
---

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

# Upgrades and compatibility

An **upgrade** moves a running deployment from the release it is on to a newer one while its state, secrets, and resource identities stay exactly where they are. Where a first deployment provisions those things, an upgrade has to preserve every one of them, including the auth database, the credential encryption keys, and the state paths. This page covers what a 0.x release may change, the procedure on each target, what to verify afterwards, and the rules on migrations and downgrades.

## Prerequisites

- **The destination release notes.** They state the supported starting versions, the required operator actions, the migrations, and the rollback limits. Nothing below replaces reading them.
- **A record of what you run now.** The source commit and version, and the deployment configuration. On Cloudflare, also the account, Worker name, deployed version, traffic allocation, and bindings.
- **A tested recovery point.** On Node, the stopped backup procedure on [Node](/operate/node). On Cloudflare, the release-specific procedure for every affected store, not `AUTH_DB` alone.
- **Somewhere to rehearse.** An isolated copy or an approved disposable environment, never a second copy answering the same Slack workspace.

## What a release may change

- **0.x releases may change APIs, configuration, or schemas.** The first tagged release establishes the versioned baseline. Before it, older experimental schemas may be incompatible, and there is no implied upgrade path from an unlisted experimental schema.
- **The release notes carry the contract.** Prerequisites, installation links, changes, known limitations, supported upgrade origins, migrations, and recovery limits. A 0.x release also states its experimental status.
- **A release is a source tag, not a package.** Chickpea is not published to npm. A release is a SemVer tag such as `v0.1.0` plus a GitHub release. A published tag never moves; a correction ships as a new version.
- **Updates are manual.** The Deploy to Cloudflare button clones the repository rather than forking it, so a new release reaches your deployment only when you redeploy it.
- **An incompatible schema is not permission to delete data.** A disposable pre-release installation may be recreated only when its operator explicitly accepts losing its data.

## Upgrade a deployment

1. **Confirm the starting version is supported**

   Read the destination release notes and check that the version you run is listed as a supported upgrade origin. Record the current source and version alongside the deployment configuration.
2. **Establish a tested recovery point**

   A backup is not proven until its restore has been tested. On Cloudflare, follow the release-specific procedure for all affected stores; stop if it needs a recovery capability you have not established yet.
3. **Rehearse on an isolated copy**

   Run the upgrade first on an isolated copy or an approved disposable environment. Preserve state paths, the auth secret, encryption keys, and existing resource IDs in the rehearsal, because those are what the real upgrade must keep.
4. **Stop or drain traffic, then apply the release**

   Drain as the release notes require, then follow **On Cloudflare** or **On Node** below. Do not let an old and a new copy answer the same Slack workspace at the same time.

The fifth step is verification, and it has its own section below.

## On Cloudflare

Check out the release in a clone, install its exact lockfile, and redeploy with the guarded wrapper.

```sh
git checkout <release-tag>
npm ci
npm run deploy
```

If your deployment runs the coding sandbox, choose the profile explicitly instead: `npm run deploy:sandbox`, or set the build variable `CHICKPEA_DEPLOY_PROFILE=sandbox`. The Deploy to Cloudflare button's supported default is the slim `core` profile, so it does not preserve container infrastructure on its own. Removing the variable and deploying `core` returns you to the slim Worker, and stored sandbox enablement does nothing without the binding.

The wrapper is what makes the redeploy safe, which is why bare `wrangler deploy` is refused:

- **It preserves the deployed auth database.** A generated artifact pointing at another database stops the deploy with `refusing to replace customer auth data`.
- **It applies the reviewed Better Auth migrations before upload.** D1 migrations are forward-only and idempotent, so a deploy that fails later can be rerun and resumes from D1's migration ledger.
- **It keeps the secrets that already exist.** `CHICKPEA_AUTH_SECRET` and the credential encryption keys are minted only on a deployment that has none. Half a credential key set stops the deploy until both `CHICKPEA_CREDENTIAL_KEY_CURRENT_ID` and its versioned slot are restored.
- **It refuses destructive class changes.** An artifact that deletes or renames the protected Durable Object classes `TagStateStore`, `Sandbox`, or `ContainerProxy` never reaches upload.

## On Node

Build the new checkout beside the old one, point `/opt/chickpea/current` at it, and restart the service against the same state paths.

```sh
git checkout <release-tag>
npm ci
npm run flue:build
sudo systemctl restart chickpea
```

State lives outside the checkout, in the state directory such as `/var/lib/chickpea`, so replacing `/opt/chickpea/current` leaves the databases and the credential keyring untouched. Keep the same `CHICKPEA_AUTH_SECRET` and the same keyring file: losing encryption keys makes stored credentials unusable. The entry point handles SIGTERM and waits for shutdown with a 60 second internal deadline, so allow the stop to finish before the new process starts.

## Verify

A successful upload or a running process is not acceptance. Before you reopen traffic, confirm all of these against the upgraded deployment:

- Sign in to Admin with Slack.
- The existing Agents and their connections are still there.
- A real mention in Slack gets a reply from this deployment.
- Memory and the schedules that matter still behave. On Cloudflare, confirm an approved schedule fires and stops when it is paused.

An upgrade removes no Agent. A deployment installed while Chickpea still seeded a starter Agent named Sprout keeps that Agent; only fresh installs start with an empty Agents list.

Then record the source commit, the deployed version, and the bindings, so the next upgrade starts from a known origin.

## Migrations

- **Never edit already-applied migration SQL.** Its digest is part of the auth database contract, and the migration ledger stores the reviewed digests. Add a forward migration instead, and test both fresh creation and the upgrade from the preceding supported release.
- **An unrecognized chain stops the deploy.** After migrations run, the wrapper reads the remote schema back and fails with `AUTH_DB contains an incompatible reviewed Better Auth migration-chain schema` rather than uploading a Worker onto a schema it does not expect.
- **A database with pre-existing tables but no compatible ledger is incompatible.** So is a digestless ledger, or a different applied digest. Stop and preserve its data.

## Downgrades and recovery

Reverting code does not undo a schema migration and does not recover deleted data. Downgrade only when the release notes declare it safe; otherwise use the tested full recovery procedure or ship a forward fix.

> **Never reset a production database to make an upgrade pass**
>
> An incompatible schema is a reason to stop, not a reason to delete state. Do not silently reset a database, and do not edit applied migration SQL to make a check succeed.

Recovery is not symmetric across the two targets. On Cloudflare, app and runtime state sits in Durable Objects while auth data sits in D1, and Chickpea provides no complete cross-store snapshot and restore tool, so restoring `AUTH_DB` alone does not restore the deployment. On Node, a restore rolls the whole state directory back in time and may lose recent work or replay events; reconcile that interval before reopening ingress.

## Next steps

- [Cloudflare](/operate/cloudflare): what the deploy wrapper checks, the two profiles, and the secrets it manages.
- [Node](/operate/node): the build, the systemd unit, and the stopped backup procedure the recovery point depends on.
- [Deploy and operate](/operate): the rest of this section, including configuration.
- [How Chickpea works](/start/how-it-works): what the Durable Objects, D1, and SQLite files are holding.

Source: https://docs.chickpea.co/operate/upgrades/index.mdx
