---
title: "Performance"
description: "Optimize OG image generation for fast rendering and minimal HTML overhead."
canonical_url: "https://nuxtseo.com/docs/og-image/guides/performance"
---

> Index of every page on this site: [llms.txt](https://nuxtseo.com/llms.txt)

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 for up to 72 hours. Its default memory cache limits stored entries to 64 MiB.
It 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

The default cache evicts the least recently used entries when it reaches its limit. Evicted images render again on request.
The cache is **lost on server restart**.

To keep cached images across restarts, configure [Nitro's cache storage](https://nitro.build/guide/cache) through `nitro.storage.cache`.
Redis and Cloudflare KV support automatic expiry. The module uses your configured driver instead of its bounded default.
Use `runtimeCacheStorage` for a separate mount or a different memory limit.

Append `?purge=<token>`{lang="html"} to an OG image URL to drop its internal cache entry. The token is the URL signing secret.

::callout{icon="i-heroicons-arrow-right" to="/docs/og-image/guides/runtime-cache"}
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:

```vue [components/OgImage/BlogPost.takumi.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>
```

::tip
**Prerendered images are unaffected.** The module automatically switches to short hash-based URLs (`/_og/s/o_1whacq.png`) for any path over 200 characters, or any path that holds a comma, a plus sign, or another reserved character.
::

## 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.

```ts [nuxt.config.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.

## Sitemap

See the full [sitemap](https://nuxtseo.com/sitemap.md) for all pages.
