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