Skip to content
Back to Deployment

CORS Configuration

Configure Cross-Origin Resource Sharing for API access from browsers.

EdgeIntermediate

Why

CORS controls which origins can access your API — misconfiguration causes security holes or blocked requests. Cloudflare's edge network spans 330+ cities with sub-50ms p95 latency globally.

Edge functions reduce TTFB by 60-80% compared to origin servers, and Akamai reports 40% of enterprises now use edge compute in 2024.

When

APIs accessed from browser-based apps on different origins. Avoid edge functions for stateful logic requiring database writes — edge runtimes have no persistent connection pool.

Skip if you need long-running tasks (>30s) or heavy CPU computation.

How

# Next.js API route CORS import Cors from 'cors'; const cors = Cors({ origin: process.env.NODE_ENV === 'production' ? ['https://example.com', 'https://app.example.com'] : '*', methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization'], credentials: true, maxAge: 86400, }); export default async function handler(req, res) { await new Promise((resolve, reject) => cors(req, res, (err) => err ? reject(err) : resolve())); // Handle request } 4. Verify deployment — curl -I https://your-app.example.com 5. Monitor logs — check for errors in first 5 minutes 6. Rollback if needed — revert to previous version

Example

# Vercel edge CORS export default function handler(req: Request) { const origin = req.headers.get('origin'); const allowed = ['https://example.com', 'https://app.example.com']; if (!allowed.includes(origin)) { return new Response('Forbidden', { status: 403 }); } return new Response(JSON.stringify({ ok: true }), { headers: { 'Access-Control-Allow-Origin': origin, 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', 'Access-Control-Allow-Credentials': 'true', }, }); }

Common Problems

  • ⚠Preflight failing — ensure OPTIONS handler returns correct headers
  • ⚠Credentials not sent — set Allow-Credentials: true and specific origin (not *)
  • ⚠Configuration drift between environments — use infrastructure-as-code (Terraform/Pulumi) to keep dev/staging/prod identical

Best Practices

  • ✓Never use wildcard with credentials — browsers reject it
  • ✓Validate origin against allowlist — prevent CSRF
  • ✓Set up health checks and graceful shutdown — handle SIGTERM to drain in-flight requests before exit

FAQ