Version 8 introduces major improvements to performance monitoring, OpenTelemetry integration, and a new Performance API. This guide helps you migrate from v7 to v8.
Prerequisites
Before upgrading:
- Upgrade to the latest v7 version first
- Fix all deprecation warnings
- Review the v8 changelog
- Test in a non-production environment
Version 8 requires:
- Node.js 14.18+ for CJS, 18.19.1+ for ESM
- Browser ES2018+ support (no IE11)
- Next.js 13.2+
- React 16+
Installation
npm install @sentry/browser@^8.0.0
# or
yarn add @sentry/browser@^8.0.0
Major Changes
The biggest change in v8 is the new Performance API based on OpenTelemetry.
Before (v7):
const transaction = Sentry.startTransaction({ name: 'my-transaction' });
const span = transaction.startChild({ op: 'db.query' });
try {
const result = await query();
span.finish();
transaction.finish();
return result;
} catch (error) {
span.finish();
transaction.finish();
throw error;
}
After (v8):
import { startSpan } from '@sentry/browser';
const result = await startSpan(
{ name: 'my-transaction', op: 'task' },
async (span) => {
return await startSpan(
{ name: 'db.query', op: 'db' },
async () => {
return await query();
}
);
}
);
The new API automatically handles span finishing and error handling. Spans are automatically finished when the callback completes.
2. Package Removals
@sentry/tracing
Before (v7):
import * as Sentry from '@sentry/browser';
import { BrowserTracing } from '@sentry/tracing';
Sentry.init({
dsn: '__DSN__',
integrations: [new BrowserTracing()],
});
After (v8):
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: '__DSN__',
integrations: [Sentry.browserTracingIntegration()],
});
@sentry/integrations
Before (v7):
import { RewriteFrames } from '@sentry/integrations';
Sentry.init({
integrations: [new RewriteFrames()],
});
After (v8):
import { rewriteFramesIntegration } from '@sentry/browser';
Sentry.init({
integrations: [rewriteFramesIntegration()],
});
@sentry/replay
Before (v7):
import { Replay } from '@sentry/replay';
Sentry.init({
integrations: [new Replay()],
});
After (v8):
import { replayIntegration } from '@sentry/browser';
Sentry.init({
integrations: [replayIntegration()],
});
3. Hub to Scope API
The Hub API is deprecated in favor of the new Scope API.
Before (v7):
const hub = Sentry.getCurrentHub();
const client = hub.getClient();
Sentry.configureScope((scope) => {
scope.setTag('key', 'value');
});
After (v8):
const client = Sentry.getClient();
Sentry.getCurrentScope().setTag('key', 'value');
4. Integration Interface Changes
All integrations are now functions instead of classes.
Before (v7):
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: '__DSN__',
integrations: [
new Sentry.Integrations.Breadcrumbs(),
new Sentry.Integrations.LinkedErrors(),
],
});
After (v8):
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: '__DSN__',
integrations: [
Sentry.breadcrumbsIntegration(),
Sentry.linkedErrorsIntegration(),
],
});
Node.js Specific Changes
Initialization Order
In v8, Sentry MUST be initialized before any other imports.
Before (v7):
import express from 'express';
import * as Sentry from '@sentry/node';
Sentry.init({ dsn: '__DSN__' });
const app = express();
After (v8):
import * as Sentry from '@sentry/node';
// Initialize FIRST
Sentry.init({ dsn: '__DSN__' });
// Then import other modules
import express from 'express';
const app = express();
Express Error Handler
Before (v7):
app.use(Sentry.Handlers.requestHandler());
app.use(Sentry.Handlers.tracingHandler());
// Routes...
app.use(Sentry.Handlers.errorHandler());
After (v8):
// No request or tracing handler needed
// Just add the error handler
app.use(Sentry.setupExpressErrorHandler(app));
In v8, instrumentation happens automatically via OpenTelemetry. You only need the error handler.
Framework-Specific Migration
Next.js
v8 requires using the instrumentation hook.
1. Enable instrumentation hook (Next.js 13-14):
// next.config.js
module.exports = {
experimental: {
instrumentationHook: true, // Not needed in Next.js 15+
},
};
2. Create instrumentation.ts:
// instrumentation.ts
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
await import('./sentry.server.config');
}
if (process.env.NEXT_RUNTIME === 'edge') {
await import('./sentry.edge.config');
}
}
3. Update withSentryConfig:
Before (v7):
module.exports = withSentryConfig(
nextConfig,
{ /* webpack plugin options */ },
{ /* SDK options */ }
);
After (v8):
module.exports = withSentryConfig(nextConfig, {
// Combined options
org: 'your-org',
project: 'your-project',
});
React Router
Before (v7):
import { reactRouterV6Instrumentation } from '@sentry/react';
Sentry.init({
integrations: [
new BrowserTracing({
routingInstrumentation: reactRouterV6Instrumentation(
useEffect,
useLocation,
useNavigationType,
createRoutesFromChildren,
matchRoutes
),
}),
],
});
After (v8):
import { reactRouterV6BrowserTracingIntegration } from '@sentry/react';
Sentry.init({
integrations: [
reactRouterV6BrowserTracingIntegration({
useEffect,
useLocation,
useNavigationType,
createRoutesFromChildren,
matchRoutes,
}),
],
});
API Changes
Removed APIs
Before:
Sentry.configureScope((scope) => {
scope.setTag('key', 'value');
});
After:
Sentry.getCurrentScope().setTag('key', 'value');
getActiveTransaction
Before:
const transaction = Sentry.getActiveTransaction();
After:
import { getActiveSpan, getRootSpan } from '@sentry/browser';
const span = getActiveSpan();
const rootSpan = getRootSpan(span);
spanStatusfromHttpCode
Before:
import { spanStatusfromHttpCode } from '@sentry/tracing';
const status = spanStatusfromHttpCode(200);
After:
import { getSpanStatusFromHttpCode } from '@sentry/browser';
const status = getSpanStatusFromHttpCode(200);
Behavior Changes
tracePropagationTargets
In v7, tracePropagationTargets defaulted to ['localhost', /^\/(?!\/)/].
In v8, it defaults to same-origin requests only.
Migration:
Sentry.init({
dsn: '__DSN__',
// Explicitly set if you need different behavior
tracePropagationTargets: [
'localhost',
/^https:\/\/api\.myapp\.com/,
],
});
Severity Enum
Before:
import { Severity } from '@sentry/types';
scope.setLevel(Severity.Warning);
After:
import type { SeverityLevel } from '@sentry/types';
const level: SeverityLevel = 'warning';
scope.setLevel(level);
Step-by-Step Migration
1. Update Dependencies
npm install @sentry/browser@^8.0.0
# Remove deprecated packages
npm uninstall @sentry/tracing @sentry/integrations @sentry/replay
2. Update Imports
// Before
import { BrowserTracing } from '@sentry/tracing';
import { Replay } from '@sentry/replay';
import { RewriteFrames } from '@sentry/integrations';
// After
import {
browserTracingIntegration,
replayIntegration,
rewriteFramesIntegration,
} from '@sentry/browser';
3. Update Integrations
// Before
Sentry.init({
integrations: [
new BrowserTracing(),
new Replay(),
],
});
// After
Sentry.init({
integrations: [
browserTracingIntegration(),
replayIntegration(),
],
});
// Before
const transaction = Sentry.startTransaction({ name: 'my-op' });
try {
const result = await doWork();
transaction.finish();
return result;
} catch (error) {
transaction.finish();
throw error;
}
// After
import { startSpan } from '@sentry/browser';
const result = await startSpan({ name: 'my-op' }, async () => {
return await doWork();
});
5. Update Scope Usage
// Before
Sentry.configureScope((scope) => {
scope.setTag('key', 'value');
});
// After
Sentry.getCurrentScope().setTag('key', 'value');
6. Test Thoroughly
- Test error capturing
- Test performance monitoring
- Verify source maps
- Check integrations
Migration Checklist
Automated Migration
Sentry provides a migration tool:
This tool automatically updates:
- Integration syntax
- Import statements
- Performance API calls
- Scope API usage
Always review the automated changes before committing. Test thoroughly!
Getting Help
If you encounter issues:
- Check the full v8 migration guide
- Search GitHub issues
- Ask in Discord
- Review the v8 changelog
Next Steps
v8 to v10 Migration
Upgrade from v8 to the latest version
Performance Monitoring
Learn the new Performance API