Skip to main content
The Sentry Bun SDK is in Beta. Please help us improve the SDK by reporting issues or giving feedback.
The Sentry Bun SDK provides error monitoring and performance tracking for applications running on the Bun JavaScript runtime.

Installation

bun add @sentry/bun

Basic Setup

Initialize Sentry as early as possible in your main entry module:
import * as Sentry from '@sentry/bun';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  
  // Performance Monitoring
  tracesSampleRate: 1.0,
  
  // Set tracesSampleRate to 1.0 to capture 100%
  // of transactions for performance monitoring.
  // We recommend adjusting this value in production.
});

// Your application code
Bun.serve({
  fetch(req) {
    return new Response('Hello from Bun!');
  },
  port: 3000,
});

Bun.serve Integration

Monitor your Bun HTTP server:
import * as Sentry from '@sentry/bun';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  tracesSampleRate: 1.0,
});

Bun.serve({
  async fetch(req) {
    try {
      const url = new URL(req.url);
      
      // Add context
      Sentry.setContext('request', {
        method: req.method,
        path: url.pathname,
      });
      
      // Your route handling
      if (url.pathname === '/') {
        return new Response('Hello World!');
      }
      
      if (url.pathname === '/error') {
        throw new Error('Test error');
      }
      
      return new Response('Not Found', { status: 404 });
      
    } catch (error) {
      Sentry.captureException(error);
      return new Response('Internal Server Error', { status: 500 });
    }
  },
  
  error(error) {
    Sentry.captureException(error);
    return new Response('Server Error', { status: 500 });
  },
  
  port: 3000,
});

Error Tracking

Automatic Error Capture

import * as Sentry from '@sentry/bun';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
});

// Uncaught errors are automatically captured
throw new Error('This will be captured');

Manual Error Capture

import * as Sentry from '@sentry/bun';

try {
  await riskyOperation();
} catch (error) {
  Sentry.captureException(error, {
    tags: {
      operation: 'user-import',
    },
    extra: {
      recordCount: 1000,
    },
  });
}

// Capture messages
Sentry.captureMessage('Something went wrong', 'warning');

Performance Monitoring

Custom Spans

import * as Sentry from '@sentry/bun';

Bun.serve({
  async fetch(req) {
    return await Sentry.startSpan(
      {
        name: 'http.server',
        op: 'http.server',
        attributes: {
          'http.method': req.method,
          'http.url': req.url,
        },
      },
      async () => {
        // Handle request
        const data = await Sentry.startSpan(
          { name: 'fetch-data', op: 'db.query' },
          async () => {
            return await fetchDataFromDatabase();
          },
        );
        
        return Response.json(data);
      },
    );
  },
  port: 3000,
});

Nested Spans

import * as Sentry from '@sentry/bun';

await Sentry.startSpan(
  { name: 'process-order', op: 'function' },
  async () => {
    await Sentry.startSpan(
      { name: 'validate-order', op: 'function' },
      async () => {
        await validateOrder(order);
      },
    );
    
    await Sentry.startSpan(
      { name: 'save-order', op: 'db.query' },
      async () => {
        await db.orders.create(order);
      },
    );
    
    await Sentry.startSpan(
      { name: 'send-confirmation', op: 'http.client' },
      async () => {
        await sendEmail(order.email);
      },
    );
  },
);

Context & User Information

Set User Context

import * as Sentry from '@sentry/bun';

Sentry.setUser({
  id: '123',
  email: '[email protected]',
  username: 'john_doe',
});

// Clear user context
Sentry.setUser(null);

Add Custom Context

import * as Sentry from '@sentry/bun';

Bun.serve({
  async fetch(req) {
    // Set context for this request
    Sentry.setContext('request', {
      method: req.method,
      headers: Object.fromEntries(req.headers),
    });
    
    Sentry.setTag('environment', 'production');
    Sentry.setTag('version', '1.0.0');
    
    // Your handler code
  },
});
import * as Sentry from '@sentry/bun';

Sentry.addBreadcrumb({
  category: 'auth',
  message: 'User logged in',
  level: 'info',
  data: {
    userId: '123',
    timestamp: Date.now(),
  },
});

Database Integration

Bun SQLite

import * as Sentry from '@sentry/bun';
import { Database } from 'bun:sqlite';

const db = new Database('mydb.sqlite');

// Wrap database queries with spans
const users = await Sentry.startSpan(
  {
    name: 'SELECT users',
    op: 'db.query',
    attributes: {
      'db.system': 'sqlite',
      'db.statement': 'SELECT * FROM users',
    },
  },
  () => {
    return db.query('SELECT * FROM users').all();
  },
);

HTTP Client Tracking

import * as Sentry from '@sentry/bun';

const response = await Sentry.startSpan(
  {
    name: 'GET https://api.example.com/data',
    op: 'http.client',
    attributes: {
      'http.method': 'GET',
      'http.url': 'https://api.example.com/data',
    },
  },
  async () => {
    try {
      const res = await fetch('https://api.example.com/data');
      
      Sentry.setTag('http.status_code', res.status);
      
      if (!res.ok) {
        throw new Error(`HTTP ${res.status}: ${res.statusText}`);
      }
      
      return await res.json();
    } catch (error) {
      Sentry.captureException(error);
      throw error;
    }
  },
);

WebSocket Support

import * as Sentry from '@sentry/bun';

Bun.serve({
  fetch(req, server) {
    const url = new URL(req.url);
    
    if (url.pathname === '/ws') {
      const upgraded = server.upgrade(req);
      if (upgraded) return undefined;
    }
    
    return new Response('WebSocket server');
  },
  
  websocket: {
    open(ws) {
      Sentry.addBreadcrumb({
        category: 'websocket',
        message: 'Client connected',
        level: 'info',
      });
    },
    
    message(ws, message) {
      try {
        Sentry.startSpan(
          { name: 'websocket.message', op: 'websocket' },
          () => {
            handleMessage(ws, message);
          },
        );
      } catch (error) {
        Sentry.captureException(error);
      }
    },
    
    error(ws, error) {
      Sentry.captureException(error, {
        tags: { type: 'websocket' },
      });
    },
  },
  
  port: 3000,
});

File System Operations

import * as Sentry from '@sentry/bun';

const content = await Sentry.startSpan(
  {
    name: 'read file',
    op: 'file.read',
    attributes: {
      'file.path': './data.json',
    },
  },
  async () => {
    try {
      const file = Bun.file('./data.json');
      return await file.text();
    } catch (error) {
      Sentry.captureException(error);
      throw error;
    }
  },
);

Cron Monitoring

import * as Sentry from '@sentry/bun';

// Monitor scheduled tasks
setInterval(async () => {
  await Sentry.withMonitor(
    'cleanup-job',
    async () => {
      await performCleanup();
    },
    {
      schedule: {
        type: 'crontab',
        value: '0 * * * *',
      },
      checkinMargin: 5,
      maxRuntime: 30,
    },
  );
}, 3600000); // Every hour

Environment Variables

import * as Sentry from '@sentry/bun';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.NODE_ENV || 'development',
  release: process.env.APP_VERSION,
  
  tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0,
});

Configuration

import * as Sentry from '@sentry/bun';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  
  // Environment
  environment: 'production',
  release: '[email protected]',
  serverName: process.env.HOSTNAME,
  
  // Performance
  tracesSampleRate: 0.2,
  
  // Error filtering
  ignoreErrors: [
    'ECONNRESET',
    'EPIPE',
  ],
  
  beforeSend(event, hint) {
    // Filter or modify events
    if (event.request) {
      // Remove sensitive headers
      delete event.request.cookies;
      delete event.request.headers?.['authorization'];
    }
    return event;
  },
  
  beforeBreadcrumb(breadcrumb, hint) {
    // Filter or modify breadcrumbs
    if (breadcrumb.category === 'console') {
      return null;
    }
    return breadcrumb;
  },
});

Best Practices

Initialize Early

Call Sentry.init() at the very beginning of your main module.

Use Spans

Wrap important operations with spans to track performance.

Error Context

Add context and tags to make debugging easier.

Sample Rates

Adjust sample rates in production to control costs.

Bun-Specific Features

Bun.serve Performance

The Bun runtime is optimized for performance. Sentry adds minimal overhead:
  • Automatic request tracking
  • Native async context propagation
  • Fast error capture

Memory Usage

The SDK is optimized for Bun’s memory management:
// Enable memory tracking
Sentry.setContext('memory', {
  rss: process.memoryUsage().rss,
  heapUsed: process.memoryUsage().heapUsed,
});

Common Patterns

import * as Sentry from '@sentry/bun';

Sentry.init({ dsn: 'YOUR_DSN_HERE' });

const routes = {
  '/api/users': handleUsers,
  '/api/posts': handlePosts,
};

Bun.serve({
  async fetch(req) {
    const url = new URL(req.url);
    const handler = routes[url.pathname];
    
    if (!handler) {
      return new Response('Not Found', { status: 404 });
    }
    
    try {
      return await Sentry.startSpan(
        {
          name: `${req.method} ${url.pathname}`,
          op: 'http.server',
        },
        () => handler(req),
      );
    } catch (error) {
      Sentry.captureException(error);
      return new Response('Error', { status: 500 });
    }
  },
  port: 3000,
});

Next Steps

Bun Documentation

Official Bun documentation

Performance

Deep dive into performance monitoring

Source Maps

Upload source maps for production

Deployment

Deploy Bun applications

Build docs developers (and LLMs) love