Migrate from Sentry to Temps

To move error tracking from Sentry to Temps, keep the Sentry SDK you already use and point it at a Temps DSN. Apps you deploy on Temps get that DSN automatically, so for them the switch is a redeploy. Then move your source maps and alert rules, run both for a while, and cancel Sentry once Temps shows what you need. Your past Sentry issues don't move: Temps can't import them.

For what you gain and give up, see Temps vs Sentry. Error tracking is a Beta feature in Temps: event fidelity and ingest limits are still being hardened (see feature maturity).


What carries over

Temps reads the same envelopes the Sentry SDKs send, but it only stores error events. Check this table against the Sentry features you rely on before you start.

In SentryOn Temps
Errors, stack traces, breadcrumbs, user context, tags, extra contextStored and grouped (error grouping)
Releases and environmentsSupported. On git deploys Temps sets SENTRY_RELEASE to the commit SHA
JavaScript source mapsCaptured automatically on git deploys, or uploaded with sentry-cli 2.x (below)
AlertsNew issue, regression, frequency, new user, user count and status change rules, sent by email, Slack or webhook
Issue assignmentAssign an error group to a person
Performance (transactions, spans)Accepted but not stored. Use OpenTelemetry tracing
Release health (sessions)Accepted but not stored
Session ReplaySkipped. Use Temps Session Replay
Profiling, Crons, Logs, User Feedback, attachmentsSkipped
Cron monitorsUse cron jobs and uptime monitors
Native debug files (dSYM, ProGuard, PDB), minidumpsNot supported. Go, Rust and other native languages can upload raw source instead
GitHub issue links, suspect commits, ownership rules, issue commentsNot available
Past issues and eventsNot imported

"Skipped" and "not stored" both mean Temps accepts the envelope item and answers 200, so the SDK doesn't log errors. The data is simply dropped.


Get a Temps DSN

A DSN belongs to a project and environment. Deploying to an environment creates its DSN if it doesn't exist yet. For an app that runs somewhere else, create one yourself:

Get the project's DSN

  1. 1

    Open the project's error tracking setup page at https://<temps_app>/projects/<project_slug>/errors?tab=setup.

  2. 2

    Copy the DSN.

    Checkpoint: It has the form https://<public_key>@<temps_app>/<project_id>, where the public key is 64 hex characters.

The DSN looks like a Sentry DSN, and the SDK treats it as one:

https://<public_key>@<temps_app>/<project_id>

Pass --environment-id to dsn get-or-create to get the DSN for a specific environment, so staging and production errors stay apart.


Switch the DSN

Apps deployed on Temps

On every deploy, Temps sets SENTRY_DSN to the environment's DSN. For frontend presets it also sets the variable your bundler exposes to the browser:

PresetBrowser DSN variableBrowser tunnel variable
Next.jsNEXT_PUBLIC_SENTRY_DSNNEXT_PUBLIC_SENTRY_TUNNEL
NuxtNUXT_PUBLIC_SENTRY_DSNNUXT_PUBLIC_SENTRY_TUNNEL
Vite, React, Vue, SolidStart, RemixVITE_SENTRY_DSNVITE_SENTRY_TUNNEL
SvelteKit, Astro, RsbuildPUBLIC_SENTRY_DSNPUBLIC_SENTRY_TUNNEL
DocusaurusREACT_APP_SENTRY_DSNREACT_APP_SENTRY_TUNNEL

Temps manages these variables, and they replace any value you set with the same name. If your Sentry.init already reads them, the next deploy sends errors to Temps without a code change. The Node, Python and Go SDKs read SENTRY_DSN themselves when you don't pass dsn.

If your code has the Sentry DSN hard-coded, or reads it from a variable with another name, change it to read the variable above:

Read the DSN Temps sets

// instrumentation-client.ts (or sentry.client.config.ts)
import * as Sentry from '@sentry/nextjs';

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  // Same-origin route on your app's domain, so ad blockers don't drop events
  tunnel: process.env.NEXT_PUBLIC_SENTRY_TUNNEL,
});

The tunnel is optional. The browser can also post straight to the Temps DSN, which allows cross-origin requests.

Apps running elsewhere

Temps doesn't need to host the app. Set the DSN from Get a Temps DSN wherever the app reads its Sentry DSN today, usually SENTRY_DSN, and redeploy. Don't use the tunnel variable for these apps: the tunnel route only exists on domains Temps serves.


Run both side by side

Sending every event to both Sentry and Temps for a week or two lets you compare them before you cancel. The JavaScript SDKs can do this with makeMultiplexedTransport: when its matcher returns a list of DSNs, the SDK sends each event to all of them.

Keep your Sentry DSN under a name Temps doesn't manage, such as NEXT_PUBLIC_LEGACY_SENTRY_DSN, because Temps replaces SENTRY_DSN and the browser variables on every deploy.

Send to Sentry and Temps

import * as Sentry from '@sentry/nextjs'; // or '@sentry/react', '@sentry/browser'

const dsns = [
  process.env.NEXT_PUBLIC_SENTRY_DSN,        // Temps, set on every deploy
  process.env.NEXT_PUBLIC_LEGACY_SENTRY_DSN, // your sentry.io DSN
].filter((dsn): dsn is string => Boolean(dsn));

Sentry.init({
  dsn: dsns[0],
  transport: Sentry.makeMultiplexedTransport(Sentry.makeFetchTransport, () => dsns),
  // No `tunnel` here: a tunnel would route the Sentry copy to Temps as well
});

Other SDKs have no built-in way to send to two DSNs. For them, switch one environment at a time: point staging at Temps, check it for a few days, then production.


Source maps

Temps matches source maps to events by release and file path, and skips events that have no release. Whichever way you upload, the release your SDK reports must match the release the maps are stored under.

Git deploys: captured automatically

After a git deploy of a JavaScript project, Temps copies the .map files out of the built image and stores them under the commit SHA. It looks in .next/static and .next/server for Next.js, dist/assets for Vite, and dist and build/static for other presets. Nothing is uploaded from your build, so you don't need sentry-cli or an auth token. Three things have to be true:

  1. The build writes .map files and keeps them in the image. In Next.js, set productionBrowserSourceMaps: true. In Vite, set build.sourcemap to true or 'hidden'.
  2. The Sentry build plugin isn't deleting or uploading them. Temps sets SENTRY_AUTH_TOKEN, SENTRY_URL, SENTRY_ORG and SENTRY_PROJECT on git deploys, so the plugin will try to upload to Temps, and current plugins use an upload method Temps doesn't accept. Turn its source map handling off. Temps only fills these in when you haven't set them, so delete any SENTRY_AUTH_TOKEN, SENTRY_ORG and SENTRY_PROJECT you copied over from Sentry from the project's environment variables. Otherwise your sentry.io credentials are sent to Temps.
  3. The browser reports the commit SHA as its release. Temps sets SENTRY_RELEASE to the commit SHA during the build and at runtime. Server SDKs read it themselves; browser code needs it inlined at build time.

next.config.mjs

import { withSentryConfig } from '@sentry/nextjs';

const nextConfig = {
  productionBrowserSourceMaps: true,
  env: {
    // Inlined into the client bundle; pass it as `release` to Sentry.init
    NEXT_PUBLIC_SENTRY_RELEASE: process.env.SENTRY_RELEASE,
  },
};

export default withSentryConfig(nextConfig, {
  sourcemaps: { disable: true }, // Temps captures the maps from the image
});

instrumentation-client.ts

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  tunnel: process.env.NEXT_PUBLIC_SENTRY_TUNNEL,
  release: process.env.NEXT_PUBLIC_SENTRY_RELEASE,
});

With productionBrowserSourceMaps, anyone can download the maps from your site, as with any public source map. If that's a problem, upload them from CI instead and delete them from the build output.

Image deploys and other CI: upload with sentry-cli 2.x

Temps implements Sentry's older per-file release upload, not chunked uploads or artifact bundles. sentry-cli 3.x only does chunked uploads, so pin 2.x. When the server refuses chunked uploads, 2.x falls back to the per-file upload, which needs a release and a single project:

SENTRY_URL=https://<temps_app> \
npx @sentry/cli@2 sourcemaps upload \
  --auth-token "<dsn_public_key>" \
  --org temps \
  --project <project_slug> \
  --release "$GIT_SHA" \
  ./dist
  • --auth-token takes the DSN's public key (the part before @) or a Temps deployment token.
  • --org is ignored; any value works.
  • --release must match the release in Sentry.init. For image deploys, Temps sets SENTRY_RELEASE to the commit SHA, or to the image tag if there's no commit.
  • sentry-cli prints a deprecation notice about the fallback. That's expected.
  • The paths must match your site's URLs. Temps stores each file as ~/ plus its path inside the directory you upload, and matches that against the URL path in the stack frame. It doesn't fall back to the file name. Uploading ./dist works when dist/assets/app.js is served at /assets/app.js. To upload a subfolder, add --url-prefix with the path it is served under: for ./dist/assets, use --url-prefix '~/assets'.

Native languages (Go, Rust) report original file and line already. To show code around each frame, turn on source context.


Alerts

Sentry alert rules don't carry over, so recreate the ones you need. Every Temps project starts with two rules: New issue detected and Regression detected, each with a 30-minute cooldown.

  1. Open Notifications in the Temps console and add a provider (email, Slack or webhook) with a route, so alerts reach someone. See Set up a notification channel.
  2. Open the project's alert rules at https://<temps_app>/projects/<project_slug>/errors/alert-rules.
  3. Add a rule for each Sentry alert you want to keep. The triggers are a new issue, a regression, a frequency threshold (events in a time window), a new affected user, an affected-user count, and a status change.

Temps can also propose a fix for an error group as a pull request, an Experimental feature. See AI Autofixer.


Turn off what Temps ignores

After cutover, stop sending data Temps drops. It costs bandwidth and, in the browser, page weight:

  • Session Replay: remove replayIntegration() and the replaysSessionSampleRate and replaysOnErrorSampleRate options. Add Temps Session Replay instead.
  • Tracing: set tracesSampleRate to 0, or remove it, unless you still send traces to Sentry. For traces in Temps, use OpenTelemetry.
  • Profiling: remove the profiling integration.
  • Feedback: remove feedbackIntegration(). Temps drops user feedback.
  • Logs and cron check-ins: stop sending them to the Temps DSN.

Verify and cut over

  1. Send a test error: Sentry.captureException(new Error('Test error from Temps')). It should appear on the project's Errors page, and in bunx @temps-sdk/cli errors list --project-id <id>.
  2. Throw an error from minified browser code and check that the stack trace shows original file names. If it doesn't, compare the event's release and file paths with the release and paths the maps are stored under (bunx @temps-sdk/cli errors sourcemaps list --project-id <id> --release <release> shows each stored path).
  3. While both run, compare new issues day by day. Expect some differences: Temps groups with stack-trace fingerprints and local similarity matching, so issues that Sentry merges can show up separately. Use custom fingerprints where it matters.
  4. Remove the Sentry DSN and the multiplexed transport, then downgrade or cancel the Sentry plan. Keep the Sentry account for as long as you need its history; it can't be moved.

Each DSN accepts up to 1,000 requests a minute. Above that Temps answers 429 with Retry-After: 60, and the SDKs drop events until the minute is up. If an error loop can exceed that, lower sampleRate. Temps doesn't expire error events, so plan disk space for them; events are compressed after 7 days.


Next steps

Last updated

Was this page helpful?