Performance
Real-world benchmarks and optimization strategies
OGX is engineered for speed. This page documents real-world performance metrics and provides strategies to optimize your OG image generation.
Benchmark Results
The following benchmarks were run on Node.js 24 with 100 iterations per scenario.
| Scenario | Mean | Median | P90 | Notes |
|---|---|---|---|---|
| Minimal Preset | 39.23ms | 38.46ms | 42.68ms | Fast and lightweight, perfect for simple images and blogs. |
| Social Preset | 55.63ms | 54.89ms | 58.91ms | Rich gradients and layouts with optimized rendering. |
| Docs Preset | 46.96ms | 46.11ms | 50.98ms | Ideal for documentation pages or content-heavy layouts. |
| Custom Layout | 47.5ms | 46.8ms | 52.1ms | Builder API performs similarly to presets. |
| With Cache | 0.03ms | 0.02ms | 0.04ms | 1000x faster than cold render. Instant retrieval via LRU cache. |
[!TIP] Cache v2 provides sub-millisecond response times using FNV-1a hashing and LRU eviction.
Why OGX is Fast
1. No Browser Required
Unlike Puppeteer-based solutions, OGX uses Satori for layout and Resvg for rasterization—both are native/WASM-based and don't require a browser instance.
2. Parser v2 with O(1) Lookups
OGX uses a high-performance parser with Map-based lookup tables for ~170 static classes. Dynamic classes are handled by modular prefix handlers. Multi-level caching ensures parsed classes are reused across elements.
3. Cache v2 with LRU Eviction
Fast sync hashing using FNV-1a (~20x faster than SHA-256) combined with O(1) LRU eviction. Memory-bounded with configurable TTL support.
Optimization Strategies
Use Simpler Presets
All presets in v0.2.0 are optimized for performance:
// Fastest (~39ms)
await ogx({ preset: "minimal", title: "Hello" });
// Fast (~55ms)
await ogx({ preset: "social", title: "Hello", brand: "OGX" });
// Fast (~47ms)
await ogx({ preset: "docs", title: "Documentation" });Enable Caching
Always enable caching in production for repeated configurations:
await ogx({
preset: "docs",
title: "My Page",
cache: true, // Enable built-in cache
});Pre-register Fonts
Register fonts before rendering to avoid per-request font loading:
import { fontRegistry } from "@ogxjs/core";
// Do this once at startup
await fontRegistry.registerInterFromUrl([400, 700]);Use Static Generation
In Next.js, prefer static generation over on-demand rendering:
// app/og/[slug]/route.ts
export const dynamic = "force-static";
export const revalidate = 3600; // Revalidate every hour
export async function GET(req: Request) {
return ogxResponse({ preset: "docs", title: "..." }, req);
}Run Benchmarks Yourself
You can run the official benchmarks locally:
pnpm -F @ogxjs/core benchThis will generate:
benchmarks/results.json- Raw databenchmarks/BENCHMARKS.md- Formatted report
Environment
Benchmarks were run on:
- Runtime: Node.js v24.12.0
- Platform: Linux (x64)
- Iterations: 100 per scenario