OG Image Performance Budget: File Size, Dimensions, and Speed Limits
The exact file size limits, dimension requirements, and response time budgets for og:image across Twitter, LinkedIn, Facebook, Discord, and Slack — and how to stay within them.
Why OG image performance matters
Social crawlers (Twitter, LinkedIn, Facebook, Discord, Slack) fetch your og:image when someone shares a link. If the image is too large, too slow, or has wrong dimensions, the crawler either skips it or shows a broken preview.
Performance limits exist because crawlers operate under tight timeouts and file size budgets to avoid abuse and ensure reliable preview generation at scale.
Platform limits reference table
| Platform | Max file size | Min dimensions | Recommended | Timeout |
|---|---|---|---|---|
| Twitter/X | 5 MB | 144×144 | 1200×628 | ~4s |
| 5 MB | 1200×627 | 1200×627 | ~3s | |
| 8 MB | 200×200 | 1200×630 | ~5s | |
| Discord | ~8 MB | No strict min | 1200×630 | ~10s |
| Slack | ~2 MB | No strict min | 1200×628 | ~5s |
| 300 KB | 300×200 | 1200×630 | ~3s |
Note: Platform limits are subject to change and some are based on observed behavior rather than official documentation.
Safe OG image budget targets
To reliably pass all platforms, aim for:
- File size: Under 300 KB (well within all limits; fits WhatsApp's strict budget)
- Dimensions: 1200×628 or 1200×630 (satisfies LinkedIn's minimum and Twitter's recommended)
- Format: JPEG for photos/complex images, PNG for text-heavy or transparent OG images
- Response time: Under 3 seconds from the og:image URL (serve from CDN, not origin)
- HTTPS: Required by all platforms — HTTP og:image URLs are rejected
Optimizing dynamic OG images
Dynamic OG images (generated via Vercel OG, Satori, or Puppeteer) are the most common source of performance issues:
// Option 1: Cache at CDN edge (Vercel)
// app/api/og/route.tsx
export async function GET(request: Request) {
// ... generate image ...
return new ImageResponse(jsx, {
width: 1200,
height: 630,
headers: {
// Cache for 7 days at CDN edge — crucial for performance
"Cache-Control": "public, max-age=604800, stale-while-revalidate=86400",
},
});
}
// Option 2: Pre-generate at build time (best for static sites)
// Use a build script that generates all OG images to /public/og/
// and references them with static URLs
// Option 3: Use Cloudinary / imgix URL-based generation
// These are CDN-native and always fast
const ogUrl = "https://res.cloudinary.com/demo/image/upload/w_1200,h_630,c_fill,q_auto,f_auto/your-base-image.jpg";Checking your OG image file size
# Check file size via curl
curl -sI https://yoursite.com/api/og?title=Test | grep -i content-length
# Check response time
curl -o /dev/null -s -w "%{time_total}\n" https://yoursite.com/api/og?title=Test
# Download and check the actual file size
curl -so /tmp/og.png https://yoursite.com/api/og?title=Test && du -sh /tmp/og.pngWhen your dynamic OG is too slow
- Add edge caching:
Cache-Control: public, max-age=86400means the second request is instant - Reduce fonts: Loading Google Fonts at runtime adds 200–500ms. Embed fonts as base64 in your OG route instead
- Use edge runtime:
export const runtime = "edge"is faster than Node.js serverless for OG generation - Avoid external image fetches: Fetching a background image at render time adds latency — inline it or use a static URL
- Switch to Satori: Satori (which ImageResponse uses) is faster than Puppeteer for text-heavy OG images
Check your OG image performance
Paste your URL into OGFixer to see how your OG image renders across platforms and diagnose any performance or size issues.
Check your OG tags free →