Skip to main content
The Sentry Vercel Edge Runtime SDK provides error monitoring and performance tracking for Edge Functions and Edge Middleware running on Vercel’s Edge Network.
The @sentry/vercel-edge package is a low-level building block. For Next.js applications on Vercel, use @sentry/nextjs which includes Edge Runtime support automatically.

Installation

npm install @sentry/vercel-edge

When to Use

Use @sentry/vercel-edge for:
  • Standalone Edge Functions on Vercel
  • Edge Middleware (if not using Next.js)
  • Custom Edge applications
For Next.js applications, use @sentry/nextjs instead, which includes full Edge Runtime support.

Basic Setup

Edge Function

// api/hello.ts
import * as Sentry from '@sentry/vercel-edge';

Sentry.init({
  dsn: 'YOUR_DSN_HERE',
  tracesSampleRate: 1.0,
  environment: process.env.VERCEL_ENV,
});

export const config = {
  runtime: 'edge',
};

export default async function handler(request: Request) {
  try {
    return new Response(
      JSON.stringify({ message: 'Hello from Edge!' }),
      {
        status: 200,
        headers: { 'Content-Type': 'application/json' },
      },
    );
  } catch (error) {
    Sentry.captureException(error);
    return new Response(
      JSON.stringify({ error: 'Internal Server Error' }),
      { status: 500 },
    );
  }
}

Edge Middleware

// middleware.ts
import * as Sentry from '@sentry/vercel-edge';
import { NextRequest, NextResponse } from 'next/server';

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

export function middleware(request: NextRequest) {
  try {
    // Your middleware logic
    const response = NextResponse.next();
    
    // Add custom headers
    response.headers.set('x-custom-header', 'value');
    
    return response;
  } catch (error) {
    Sentry.captureException(error);
    return NextResponse.next();
  }
}

export const config = {
  matcher: '/api/:path*',
};

Error Handling

Manual Error Capture

import * as Sentry from '@sentry/vercel-edge';

export const config = { runtime: 'edge' };

export default async function handler(request: Request) {
  const url = new URL(request.url);
  const userId = url.searchParams.get('userId');
  
  try {
    const user = await fetchUser(userId);
    return new Response(JSON.stringify(user));
  } catch (error) {
    Sentry.captureException(error, {
      tags: {
        function: 'fetchUser',
        userId: userId || 'unknown',
      },
      contexts: {
        request: {
          url: request.url,
          method: request.method,
        },
      },
    });
    
    return new Response(
      JSON.stringify({ error: 'User not found' }),
      { status: 404 },
    );
  }
}

Validation Errors

import * as Sentry from '@sentry/vercel-edge';

export const config = { runtime: 'edge' };

export default async function handler(request: Request) {
  if (request.method !== 'POST') {
    return new Response('Method not allowed', { status: 405 });
  }
  
  try {
    const body = await request.json();
    
    if (!body.email) {
      const error = new Error('Email is required');
      Sentry.captureException(error, {
        level: 'warning',
        tags: { validation: 'email' },
      });
      
      return new Response(
        JSON.stringify({ error: 'Email is required' }),
        { status: 400 },
      );
    }
    
    // Process valid request
    return new Response(JSON.stringify({ success: true }));
  } catch (error) {
    Sentry.captureException(error);
    return new Response('Internal Server Error', { status: 500 });
  }
}

Performance Monitoring

Custom Spans

import * as Sentry from '@sentry/vercel-edge';

export const config = { runtime: 'edge' };

export default async function handler(request: Request) {
  return await Sentry.startSpan(
    {
      name: 'edge-function-handler',
      op: 'function.edge',
    },
    async () => {
      const data = await fetchData();
      return new Response(JSON.stringify(data));
    },
  );
}

External API Calls

import * as Sentry from '@sentry/vercel-edge';

export const config = { runtime: 'edge' };

async function fetchExternalData(id: string) {
  return await Sentry.startSpan(
    {
      name: 'external-api-call',
      op: 'http.client',
      attributes: {
        'http.method': 'GET',
        'http.url': `https://api.example.com/data/${id}`,
      },
    },
    async () => {
      const response = await fetch(`https://api.example.com/data/${id}`);
      return response.json();
    },
  );
}

export default async function handler(request: Request) {
  const url = new URL(request.url);
  const id = url.searchParams.get('id');
  
  const data = await fetchExternalData(id!);
  return new Response(JSON.stringify(data));
}

Database Queries

import * as Sentry from '@sentry/vercel-edge';
import { createClient } from '@vercel/edge-config';

const edgeConfig = createClient(process.env.EDGE_CONFIG);

export const config = { runtime: 'edge' };

export default async function handler(request: Request) {
  const value = await Sentry.startSpan(
    {
      name: 'edge-config.get',
      op: 'db.query',
      attributes: {
        'db.system': 'edge-config',
      },
    },
    async () => {
      return await edgeConfig.get('feature-flag');
    },
  );
  
  return new Response(JSON.stringify({ value }));
}

Context and User Information

Request Context

import * as Sentry from '@sentry/vercel-edge';

export const config = { runtime: 'edge' };

export default async function handler(request: Request) {
  const url = new URL(request.url);
  
  Sentry.setContext('request', {
    url: request.url,
    method: request.method,
    headers: Object.fromEntries(request.headers),
  });
  
  Sentry.setContext('geo', {
    city: request.headers.get('x-vercel-ip-city'),
    country: request.headers.get('x-vercel-ip-country'),
    region: request.headers.get('x-vercel-ip-country-region'),
  });
  
  // Your handler logic
  return new Response('OK');
}

User Identification

import * as Sentry from '@sentry/vercel-edge';

export const config = { runtime: 'edge' };

export default async function handler(request: Request) {
  // Extract user from JWT or cookie
  const token = request.headers.get('authorization')?.replace('Bearer ', '');
  
  if (token) {
    const user = await verifyToken(token);
    
    Sentry.setUser({
      id: user.id,
      email: user.email,
      username: user.username,
    });
  }
  
  // Your handler logic
  return new Response('OK');
}

Edge Runtime Limitations

The Edge Runtime has limitations:
  • No Node.js APIs (fs, path, etc.)
  • Smaller bundle size limits
  • Limited execution time
  • No native modules
Sentry automatically adjusts for these constraints.

Environment Variables

Configure via Vercel dashboard or .env:
# Required
SENTRY_DSN=your-dsn-here

# Optional
SENTRY_TRACES_SAMPLE_RATE=1.0
SENTRY_ENVIRONMENT=production
SENTRY_RELEASE=1.0.0
Access Vercel system environment variables:
import * as Sentry from '@sentry/vercel-edge';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.VERCEL_ENV, // 'production', 'preview', or 'development'
  release: process.env.VERCEL_GIT_COMMIT_SHA,
});

Vercel Integration

Preview Deployments

import * as Sentry from '@sentry/vercel-edge';

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.VERCEL_ENV,
  
  // Only sample in production
  tracesSampleRate: process.env.VERCEL_ENV === 'production' ? 0.1 : 1.0,
  
  beforeSend(event) {
    // Add deployment URL to events
    if (process.env.VERCEL_URL) {
      event.tags = event.tags || {};
      event.tags.deployment_url = process.env.VERCEL_URL;
    }
    return event;
  },
});

Edge Config

Use Vercel Edge Config for feature flags:
import * as Sentry from '@sentry/vercel-edge';
import { createClient } from '@vercel/edge-config';

const edgeConfig = createClient(process.env.EDGE_CONFIG);

export const config = { runtime: 'edge' };

export default async function handler(request: Request) {
  const sentryEnabled = await edgeConfig.get('sentry-enabled');
  
  if (!sentryEnabled) {
    // Skip Sentry initialization
    return new Response('OK');
  }
  
  // Your handler with Sentry
}

Best Practices

Use Next.js SDK

For Next.js apps, use @sentry/nextjs instead of this package.

Minimize Bundle

Keep edge function bundles small for fast cold starts.

Set Context

Add geo and request data for better debugging.

Sample Wisely

Use lower sample rates in production to control volume.

Troubleshooting

Edge functions have strict size limits:
  1. Minimize dependencies
  2. Use dynamic imports where possible
  3. Check bundle analyzer output
Edge functions have execution time limits:
  1. Optimize async operations
  2. Use appropriate timeouts for external calls
  3. Consider moving heavy operations to serverless functions

Next Steps

Next.js

Use Next.js SDK for full framework support

Edge Middleware

Advanced middleware patterns

Edge Config

Use Vercel Edge Config

Vercel

Vercel deployment best practices

Build docs developers (and LLMs) love