---
title: "Performance · Nuxt OG Image · Nuxt SEO"
canonical_url: "https://nuxtseo.com/docs/og-image/guides/performance"
last_updated: "2026-08-16T09:55:34.178Z"
meta:
  description: "Optimize OG image generation for fast rendering and minimal HTML overhead."
  "og:description": "Optimize OG image generation for fast rendering and minimal HTML overhead."
  "og:title": "Performance · Nuxt OG Image · Nuxt SEO"
---

Nuxt SEO on GitHub

**OG Image v6** is here. Looking for an older version? [~~View v5 docs ~~](https://nuxtseo.com/docs/og-image/v5/getting-started/introduction).

](https://nuxtseo.com/docs/og-image/getting-started/introduction)

](https://nuxtseo.com/docs/og-image/api/define-og-image)

](https://nuxtseo.com/docs/og-image/releases/v6)

Switch to OG Image](https://nuxtseo.com/docs/og-image/getting-started/introduction)Switch to Nuxt SEO](https://nuxtseo.com/docs/nuxt-seo/getting-started/introduction)Switch to Robots](https://nuxtseo.com/docs/robots/getting-started/introduction)Switch to Sitemap](https://nuxtseo.com/docs/sitemap/getting-started/introduction)Switch to Schema.org](https://nuxtseo.com/docs/schema-org/getting-started/introduction)Switch to Link Checker](https://nuxtseo.com/docs/link-checker/getting-started/introduction)Switch to SEO Utils](https://nuxtseo.com/docs/seo-utils/getting-started/introduction)Switch to Site Config](https://nuxtseo.com/docs/site-config/getting-started/introduction)Switch to Skew Protection](https://nuxtseo.com/docs/skew-protection/getting-started/introduction)Switch to AI Ready](https://nuxtseo.com/docs/ai-ready/getting-started/introduction)

**Core Concepts**

# **Performance**

A first render takes 400-3500ms depending on renderer, but a cached render drops to 5-30ms - a 10-50x speedup. Caching is the single biggest win.

## Caching

The module caches rendered images in [**~~Nitro's default cache storage~~**](https://nitro.build/guide/cache) with a 72-hour TTL, and emits immutable `**Cache-Control**` headers so CDNs can serve cached copies without revalidation:

- **First render**: 400-1500ms (Satori), 600-2500ms (Takumi), 1000-3500ms (Browser)
- **Cached render**: 5-30ms

Nitro's default storage is in-memory, which means the cache is **lost on server restart**. For production, point Nitro's `**cache**` storage at a persistent driver (for example [**~~Redis~~**](https://redis.io) or Cloudflare KV) via `**nitro.storage.cache**`; the module picks it up automatically. Or use the module-specific `**runtimeCacheStorage**` option if you want OG images on a separate mount. Append `**?purge**` to any OG image URL to manually invalidate its cache entry.

See the [**~~Runtime Cache guide~~**](https://nuxtseo.com/docs/og-image/guides/runtime-cache) for storage drivers, cache keys, and TTL options.

## Reduce URL Size

Runtime URLs encode all options in the path. Passing many props produces long URLs, adding HTML bloat to every page. To keep URLs short:

- **Pass minimal props**: send a slug or ID and `**$fetch**` the full data inside your component
- **Use [**~~module defaults~~**](https://nuxtseo.com/docs/og-image/api/config#defaults)**: options in `**ogImage.defaults**` are excluded from URLs
- **Use [**~~route rules~~**](https://nuxtseo.com/docs/og-image/guides/route-rules)**: options resolved server-side, never encoded in the URL

```ts
// ❌ All data as props — long URL
defineOgImage('BlogPost', {
  title: post.title,
  description: post.description,
  author: post.author.name,
  category: post.category,
})

// ✅ Just a slug — short URL
defineOgImage('BlogPost', { slug: post.slug })
```

Then fetch the data inside the component:

components/OgImage/BlogPost.takumi.vue

```vue
<script setup lang="ts">
const { slug } = defineProps<{ slug: string }>()
const post = await $fetch(`/api/posts/${slug}`)
</script>

<template>
  <div class="w-full h-full flex flex-col justify-center p-12 bg-white">
    <h1 class="text-6xl font-bold">
      {{ post.title }}
    </h1>
    <p class="text-2xl text-gray-600 mt-4">
      {{ post.description }}
    </p>
  </div>
</template>
```

**Prerendered images are unaffected.** The module automatically switches to short hash-based URLs (`**/_og/s/o_1whacq.png**`) for any path exceeding 200 characters.

## Optimize Components

- **Avoid dynamic images**: use static, statically-analyzable image sources where possible. Dynamic image URLs trigger runtime fetches (100-500ms each) and dimension detection. The build step can resolve static sources ahead of time.
- **Keep font sets static**: each unique font combination forces Satori to re-parse font binaries (\~2x throughput hit). Use a consistent set across components.
- **Use local emoji packages**: default emoji rendering fetches from a remote API each render. See the [**~~Emojis guide~~**](https://nuxtseo.com/docs/og-image/guides/emojis).

## Prerender

Images generated at build time have zero runtime cost.

nuxt.config.ts

```ts
export default defineNuxtConfig({
  routeRules: {
    '/blog/**': { prerender: true }
  }
})
```

- **Short URLs**: hash mode keeps URLs compact regardless of prop count
- **Build cache**: persists across deploys ([**~~Build Cache guide~~**](https://nuxtseo.com/docs/og-image/guides/build-cache))
- **Zero Runtime**: removes all renderer code from production (81% smaller). See [**~~Zero Runtime~~**](https://nuxtseo.com/docs/og-image/guides/zero-runtime).

Even if you can't prerender everything, consider it for high-traffic pages.

**Was this page helpful?**

### **Related **

[**Runtime Cache**](https://nuxtseo.com/docs/og-image/guides/runtime-cache)

[**Build Cache**](https://nuxtseo.com/docs/og-image/guides/build-cache)

[**Zero Runtime**](https://nuxtseo.com/docs/og-image/guides/zero-runtime)

[**WhatsApp & Multiple Images** Generate multiple OG images per page for different platforms like WhatsApp.](https://nuxtseo.com/docs/og-image/guides/whatsapp) [**CLI** Use the nuxt-og-image CLI to scaffold, manage, and migrate OG image components.](https://nuxtseo.com/docs/og-image/guides/cli)