---
title: Releases and source maps
description: Name releases, upload source maps for readable browser stacks and record deploys.
---

A release is a version of your code. Telemetry joins a release through the `release` option of the [SDK](/sdk), `OPENPERF_RELEASE` on servers, or the `service.version` resource attribute in [OpenTelemetry](/opentelemetry). Use the same string everywhere: the SDK, the CLI and your build, such as a version number or a commit SHA.

A release appears under **Releases** once it is created with the CLI. One release can span several projects of the organization.

## The CLI

The `openperf` CLI comes with `@openperf/sdk` and needs Node.js 22.15 or later.

It needs an API token. Owners and admins create one under **Settings → API → New token**. The token is shown once, never expires and acts as the organization with full access to every project, so keep it in your CI secrets and revoke it when it's no longer used.

| Flag        | Variable              | Value                                                        |
| ----------- | --------------------- | ------------------------------------------------------------ |
| `--url`     | `OPENPERF_URL`        | The OpenPerf API, such as `https://api.example.com`.         |
| `--token`   | `OPENPERF_AUTH_TOKEN` | The API token, `opt_…`.                                      |
| `--project` | `OPENPERF_PROJECT`    | The project ID: the last part of the project's settings URL. |
| `--release` | `OPENPERF_RELEASE`    | The release version.                                         |

Every command needs all four. A flag wins over its variable.

## Create a release

```bash
npx openperf releases create --ref "$GITHUB_SHA"
```

This creates the release, or adds the project to an existing one. Running it again is safe: the `release.created` [webhook](/webhooks) is sent only when the project first joins. `--ref` is the commit the release was built from. With the GitHub integration and a code mapping for the project (**Settings → Integrations**), the release lists its commits since the previous release.

## Upload source maps

Browser stacks point into minified bundles. With source maps uploaded for the release, OpenPerf maps them back to your source before grouping errors.

1. Build with source maps on.
2. Upload the build output after each build:

```bash
npx openperf sourcemaps upload ./dist
```

The CLI uploads every `.map` file in the directory and its subfolders, in batches of up to 500 files. Uploading a file again for the same release replaces it.

Each map is matched to the script URL in the stack by its path inside the directory. With the default prefix `~/`, `dist/assets/app.js.map` serves `https://<any host>/assets/app.js`. When the files are served from elsewhere, pass `--url-prefix`:

| Scripts are served from                                      | `--url-prefix`             |
| ------------------------------------------------------------ | -------------------------- |
| `https://app.example.com/assets/app.js`                      | `~/` (default)             |
| `https://app.example.com/static/assets/app.js`               | `~/static/`                |
| `https://cdn.example.com/assets/app.js`, only from that host | `https://cdn.example.com/` |

Stacks are mapped when an error arrives, so upload before the release takes traffic. Only errors with the same release and project as the upload are mapped. Source maps apply to browser stacks only.

On a self-hosted server, uploads need [object storage](/self-hosting/configuration#object-storage).

## Record a deploy

A deploy says a release reached an environment. It shows on the release page and sends the `release.deployed` [webhook](/webhooks). Record it with the API token after the release is created:

```bash
RELEASE_ID=$(curl -fsS -H "Authorization: Bearer $OPENPERF_AUTH_TOKEN" \
  "https://api.example.com/api/v1/releases/lookup?projectId=$OPENPERF_PROJECT&version=$OPENPERF_RELEASE" \
  | jq -r .id)

curl -fsS -X POST "https://api.example.com/api/v1/releases/$RELEASE_ID/deploys" \
  -H "Authorization: Bearer $OPENPERF_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"environment": "production"}'
```

| Field         | Description                                                       |
| ------------- | ----------------------------------------------------------------- |
| `environment` | Required. Up to 100 characters.                                   |
| `projectIds`  | The projects deployed. Every project of the release when omitted. |
| `name`        | A label, such as a pipeline run.                                  |
| `url`         | A link to the deploy, `http` or `https`.                          |
| `startedAt`   | ISO 8601 time. Must not be after `finishedAt`.                    |
| `finishedAt`  | ISO 8601 time. Now when omitted.                                  |

**Copy release ID** in the release's menu gives the same ID by hand.

## Release health

Each release shows its errors per 1,000 transactions, failure rate, new errors, adoption over the first 48 hours, commits and deploys, compared with the previous release. Its status:

| Status        | When                                                                                                     |
| ------------- | -------------------------------------------------------------------------------------------------------- |
| **Pending**   | Fewer than 100 transactions so far.                                                                      |
| **Healthy**   | No new errors, and no growth below.                                                                      |
| **Degraded**  | New errors, or the failure rate or errors per 1,000 transactions grew to 1.2 times the previous release. |
| **Regressed** | The failure rate or errors per 1,000 transactions grew to 1.5 times the previous release.                |

Growth counts only when the failure rate rises by at least 0.5 percentage points, or errors by at least 1 per 1,000 transactions.

**Delete release** removes the release and its deploys. Its telemetry is kept.
