Skip to content
VectorFast Render docs

Caching and versions

How VectorFast Render caches renders, what goes into the cache key, how template and brand kit versions work, and how idempotency keys make retries safe.

Short answer: a render is identified by its cache key: template id and source version, brand kit version, format, size, scale, and the validated parameters. The same cache key is rendered once and then served from the edge cache or R2. Change any input, including the brand kit, and you get a new cache key and a new image.

The cache key

cache_key = sha256(
  "v1" \n template_id \n template_version_hash \n brand_kit_version \n
  format \n width \n height \n scale \n stable_json(validated params)
)
  • template_version_hash is a hash of the template's source code, so any change to a template produces new cache keys even if its version label stays the same.
  • brand_kit_version is default@1 for the built-in kit or bk_…@n for an account kit.
  • Params are validated and trimmed first, then serialized with sorted keys, so key order and surrounding whitespace do not create new entries.

POST /v1/renders returns cache_key; image responses carry it as X-Cache-Key.

Two cache layers

LayerKeyed byNotes
Cloudflare edge cacheThe full request URL (signed URLs) or the cache key (REST)Closest to the viewer; per data center
R2 object storageThe cache keyShared by REST, MCP, and signed URLs, so pixels rendered through one path are served to the others

A response tells you which layer answered: X-Cache: hit-edge, hit-r2, or miss, and cached: true in JSON. Hits never render; render_ms is 0.

Previews from POST /v1/previews and the MCP preview_render tool carry a watermark, use a separate cache key, and are only kept in the edge cache.

Billing and cache hits

Billing is not connected in early access, so every response reports credits_charged: 0. When billing is connected, a new render will spend one credit and a cache hit will spend nothing; previews stay free. See Limits and quotas.

Template versions

Every template has a semantic version (launch-post@1.0.0 in template_version). Requests can name a template as launch-post (current version) or pin the major version as launch-post@1. A pin that does not match the current major version returns 404 template_not_found, so a breaking template change can never silently change images you pinned.

Brand kit versions

Editing a brand kit, including uploading a new logo, creates a new version: bk_…@1, bk_…@2, and so on. Because the version is part of the cache key:

  • renders that name the kit without a version use its current version and pick up your changes;
  • renders that pin a version ("brand_kit": "bk_…@1") keep hitting the cache for that version;
  • signed URLs always carry a pinned version, so a URL you stored keeps its pixels after the kit changes.

Idempotent retries

Send an Idempotency-Key header (1–255 printable ASCII characters) with POST /v1/renders to make retries safe. For 24 hours, the same key with the same body returns the stored response with the same id and Idempotent-Replayed: true; the same key with a different body returns 409 invalid_params. Keys are scoped to your account. Two concurrent first requests with the same key may both render, but they produce the same pixels and cache key.

Updated 2026-10-30 · Markdown version