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 Sentry | On Temps |
|---|---|
| Errors, stack traces, breadcrumbs, user context, tags, extra context | Stored and grouped (error grouping) |
| Releases and environments | Supported. On git deploys Temps sets SENTRY_RELEASE to the commit SHA |
| JavaScript source maps | Captured automatically on git deploys, or uploaded with sentry-cli 2.x (below) |
| Alerts | New issue, regression, frequency, new user, user count and status change rules, sent by email, Slack or webhook |
| Issue assignment | Assign an error group to a person |
| Performance (transactions, spans) | Accepted but not stored. Use OpenTelemetry tracing |
| Release health (sessions) | Accepted but not stored |
| Session Replay | Skipped. Use Temps Session Replay |
| Profiling, Crons, Logs, User Feedback, attachments | Skipped |
| Cron monitors | Use cron jobs and uptime monitors |
| Native debug files (dSYM, ProGuard, PDB), minidumps | Not supported. Go, Rust and other native languages can upload raw source instead |
| GitHub issue links, suspect commits, ownership rules, issue comments | Not available |
| Past issues and events | Not 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
Open the project's error tracking setup page at https://<temps_app>/projects/<project_slug>/errors?tab=setup.
- 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:
| Preset | Browser DSN variable | Browser tunnel variable |
|---|---|---|
| Next.js | NEXT_PUBLIC_SENTRY_DSN | NEXT_PUBLIC_SENTRY_TUNNEL |
| Nuxt | NUXT_PUBLIC_SENTRY_DSN | NUXT_PUBLIC_SENTRY_TUNNEL |
| Vite, React, Vue, SolidStart, Remix | VITE_SENTRY_DSN | VITE_SENTRY_TUNNEL |
| SvelteKit, Astro, Rsbuild | PUBLIC_SENTRY_DSN | PUBLIC_SENTRY_TUNNEL |
| Docusaurus | REACT_APP_SENTRY_DSN | REACT_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:
- The build writes
.mapfiles and keeps them in the image. In Next.js, setproductionBrowserSourceMaps: true. In Vite, setbuild.sourcemaptotrueor'hidden'. - The Sentry build plugin isn't deleting or uploading them. Temps sets
SENTRY_AUTH_TOKEN,SENTRY_URL,SENTRY_ORGandSENTRY_PROJECTon 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 anySENTRY_AUTH_TOKEN,SENTRY_ORGandSENTRY_PROJECTyou copied over from Sentry from the project's environment variables. Otherwise your sentry.io credentials are sent to Temps. - The browser reports the commit SHA as its release. Temps sets
SENTRY_RELEASEto 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-tokentakes the DSN's public key (the part before@) or a Temps deployment token.--orgis ignored; any value works.--releasemust match thereleaseinSentry.init. For image deploys, Temps setsSENTRY_RELEASEto the commit SHA, or to the image tag if there's no commit.sentry-cliprints 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./distworks whendist/assets/app.jsis served at/assets/app.js. To upload a subfolder, add--url-prefixwith 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.
- 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.
- Open the project's alert rules at
https://<temps_app>/projects/<project_slug>/errors/alert-rules. - 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 thereplaysSessionSampleRateandreplaysOnErrorSampleRateoptions. Add Temps Session Replay instead. - Tracing: set
tracesSampleRateto0, 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
- Send a test error:
Sentry.captureException(new Error('Test error from Temps')). It should appear on the project's Errors page, and inbunx @temps-sdk/cli errors list --project-id <id>. - 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). - 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.
- 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.