Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/getsentry/sentry-javascript/llms.txt

Use this file to discover all available pages before exploring further.

Transport options control how the SDK sends events to Sentry, including buffering, headers, and custom endpoints.

BaseTransportOptions

From packages/core/src/types-hoist/transport.ts:
export interface BaseTransportOptions extends InternalBaseTransportOptions {
  url: string;
  headers?: { [key: string]: string };
}

export interface InternalBaseTransportOptions {
  tunnel?: string;
  bufferSize?: number;
  recordDroppedEvent: Client['recordDroppedEvent'];
}

Options

url

url
string
required
The Sentry ingestion endpoint URL. Usually generated automatically from the DSN.
{
  url: 'https://o0.ingest.sentry.io/api/0/envelope/'
}

headers

headers
Record<string, string>
Custom HTTP headers to include in requests.
Sentry.init({
  dsn: 'your-dsn',
  transportOptions: {
    headers: {
      'X-Custom-Header': 'value',
      'X-API-Key': process.env.API_KEY
    }
  }
});

bufferSize

bufferSize
number
default:"64"
Maximum number of requests to buffer before dropping events.From packages/core/src/transports/base.ts:
export const DEFAULT_TRANSPORT_BUFFER_SIZE = 64;
Example:
Sentry.init({
  dsn: 'your-dsn',
  transportOptions: {
    bufferSize: 30 // Limit concurrent requests
  }
});

tunnel

tunnel
string
Proxy endpoint for forwarding events. Useful for bypassing ad-blockers or CORS issues.
Sentry.init({
  dsn: 'your-dsn',
  tunnel: '/api/tunnel'
});

Buffer Management

The transport uses a promise buffer to manage concurrent requests:
import { makePromiseBuffer } from '@sentry/core';

const buffer = makePromiseBuffer(
  options.bufferSize || DEFAULT_TRANSPORT_BUFFER_SIZE
);

// Add request to buffer
buffer.add(requestTask).then(
  result => result,
  error => {
    if (error === SENTRY_BUFFER_FULL_ERROR) {
      // Buffer is full, event dropped
      recordEnvelopeLoss('queue_overflow');
      return Promise.resolve({});
    }
    throw error;
  }
);

Custom Transport

Create a custom transport implementation:
import { 
  createTransport, 
  BaseTransportOptions,
  TransportRequest,
  TransportMakeRequestResponse 
} from '@sentry/core';

function makeCustomRequest(
  request: TransportRequest
): Promise<TransportMakeRequestResponse> {
  return fetch(options.url, {
    method: 'POST',
    body: request.body,
    headers: {
      'Content-Type': 'application/x-sentry-envelope',
      ...options.headers
    }
  }).then(response => ({
    statusCode: response.status,
    headers: {
      'x-sentry-rate-limits': response.headers.get('x-sentry-rate-limits'),
      'retry-after': response.headers.get('retry-after')
    }
  }));
}

export function makeCustomTransport(
  options: BaseTransportOptions
) {
  return createTransport(options, makeCustomRequest);
}

Tunnel Endpoint

Implement a tunnel endpoint to proxy events:

Server-Side Tunnel

// Express.js example
import express from 'express';
import { IncomingMessage } from 'http';

const app = express();

app.post('/api/tunnel', express.raw({ type: '*/*' }), async (req, res) => {
  const envelope = req.body;
  const pieces = envelope.toString('utf8').split('\n');
  const header = JSON.parse(pieces[0]);
  
  // Forward to Sentry
  const projectId = header.dsn?.match(/\/(\d+)$/)?.[1];
  if (!projectId) {
    return res.status(400).send('Invalid DSN');
  }
  
  const upstream = `https://o0.ingest.sentry.io/api/${projectId}/envelope/`;
  
  try {
    const response = await fetch(upstream, {
      method: 'POST',
      body: envelope,
      headers: {
        'Content-Type': 'application/x-sentry-envelope'
      }
    });
    
    res.status(response.status).send();
  } catch (error) {
    res.status(500).send('Tunnel failed');
  }
});

Client Configuration

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

Sentry.init({
  dsn: 'your-dsn',
  tunnel: '/api/tunnel'
});

HTTP Client Options

For Node.js, additional HTTP options can be configured:
import * as Sentry from '@sentry/node';
import { makeNodeTransport } from '@sentry/node';
import https from 'https';

Sentry.init({
  dsn: 'your-dsn',
  transport: makeNodeTransport,
  transportOptions: {
    headers: {
      'User-Agent': 'my-app/1.0.0'
    },
    // Custom HTTP agent
    agent: new https.Agent({
      keepAlive: true,
      maxSockets: 10
    })
  }
});

Offline Support

Implement offline queueing:
import { makeOfflineTransport, makeBrowserOfflineTransport } from '@sentry/core';
import { makeFetchTransport } from '@sentry/browser';

Sentry.init({
  dsn: 'your-dsn',
  transport: makeOfflineTransport(makeFetchTransport)
});

Multiplexed Transport

Send different event types to different DSNs:
import { makeMultiplexedTransport } from '@sentry/core';
import { makeFetchTransport } from '@sentry/browser';

Sentry.init({
  dsn: 'default-dsn',
  transport: makeMultiplexedTransport(
    makeFetchTransport,
    (args) => {
      // Route errors to different DSN
      if (args.getEvent().type === 'error') {
        return [{ dsn: 'errors-dsn' }];
      }
      // Route transactions to different DSN
      if (args.getEvent().type === 'transaction') {
        return [{ dsn: 'transactions-dsn' }];
      }
      return [];
    }
  )
});

Rate Limiting

The transport automatically handles rate limiting:
// From packages/core/src/transports/base.ts

// Rate limited items are dropped
forEachEnvelopeItem(envelope, (item, type) => {
  const dataCategory = envelopeItemTypeToDataCategory(type);
  if (isRateLimited(rateLimits, dataCategory)) {
    options.recordDroppedEvent('ratelimit_backoff', dataCategory);
  } else {
    filteredEnvelopeItems.push(item);
  }
});

// Update rate limits from response
rateLimits = updateRateLimits(rateLimits, response);

Request Retry

Implement custom retry logic:
import { createTransport, BaseTransportOptions } from '@sentry/core';

function makeRequestWithRetry(
  request: TransportRequest,
  retries = 3
): Promise<TransportMakeRequestResponse> {
  return fetch(options.url, {
    method: 'POST',
    body: request.body
  })
  .then(response => {
    if (response.status >= 500 && retries > 0) {
      // Retry on server errors
      return new Promise(resolve => {
        setTimeout(() => {
          resolve(makeRequestWithRetry(request, retries - 1));
        }, 1000 * (4 - retries)); // Exponential backoff
      });
    }
    return {
      statusCode: response.status,
      headers: {
        'x-sentry-rate-limits': response.headers.get('x-sentry-rate-limits'),
        'retry-after': response.headers.get('retry-after')
      }
    };
  });
}

Compression

Enable compression for smaller payloads:
import { gzipSync } from 'zlib';
import { createTransport } from '@sentry/core';

function makeCompressedRequest(
  request: TransportRequest
): Promise<TransportMakeRequestResponse> {
  const compressed = gzipSync(request.body);
  
  return fetch(options.url, {
    method: 'POST',
    body: compressed,
    headers: {
      'Content-Type': 'application/x-sentry-envelope',
      'Content-Encoding': 'gzip'
    }
  });
}

Performance Monitoring

Monitor transport performance:
import { createTransport } from '@sentry/core';

function makeMonitoredRequest(
  request: TransportRequest
): Promise<TransportMakeRequestResponse> {
  const startTime = Date.now();
  
  return fetch(options.url, {
    method: 'POST',
    body: request.body
  })
  .then(response => {
    const duration = Date.now() - startTime;
    console.log(`Transport request took ${duration}ms`);
    
    return {
      statusCode: response.status
    };
  });
}

Best Practices

1. Set Appropriate Buffer Size

// High-traffic applications
Sentry.init({
  transportOptions: {
    bufferSize: 100 // Increase for burst traffic
  }
});

// Low-memory environments
Sentry.init({
  transportOptions: {
    bufferSize: 10 // Decrease to save memory
  }
});

2. Use Tunnel for Browser Apps

// Avoid CORS and ad-blockers
Sentry.init({
  dsn: 'your-dsn',
  tunnel: '/api/tunnel'
});

3. Add Custom Headers for Authentication

Sentry.init({
  transportOptions: {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  }
});

4. Monitor Buffer Overflow

client.on('flush', () => {
  const buffer = client.getTransport()?.getBuffer();
  if (buffer?.isFull()) {
    console.warn('Transport buffer is full');
  }
});

Build docs developers (and LLMs) love