Caching

Identical Python re-runs produce byte-identical DAGs (the DAG node IDs are content hashes). The SDK and CADbuildr’s hosted render service exploit this with several layers of cache, so a popular storefront default doesn’t pay a fresh kernel render per visitor.

You don’t configure most of this — it’s handled for you. What you do control is how cache-friendly your parameters are. This page explains the layers so you can get the highest hit rate.

Server-side render cache

CADbuildr’s render service caches rendered meshes keyed on the canonicalized DAG plus the kernel version. Because identical parameter values produce an identical DAG, two visitors who land on the same configuration share a single render — the second one gets the cached mesh response.

  • Survives JSON round-trips and emitter changes — the cache key is computed from a canonical serialization of the DAG, not its raw bytes.
  • Automatically invalidates on kernel upgrades — the kernel version is part of the key, so a redeploy re-keys the cache with no action on your side.
  • Automatically invalidates on project changes — editing your parameter schema or template DAG changes the canonical DAG, so the next render misses and refills under the new key.

A 1000-visitor configurator on a 5-parameter grid typically sees a high cache hit rate after the first hour — most visitors land on the project defaults or a small number of common configurations.

Client-side mesh-hash cache

@cadbuildr/cad-kernel-r3f keeps an in-browser geometry cache keyed on the per-mesh hash field of the render response. Two benefits:

  • Within a single render — repeated meshes (the same brick at many positions) share one BufferGeometry instead of uploading duplicates to the GPU.
  • Across renders in the same provider — already-uploaded meshes are reused, so nudging a slider only re-uploads the meshes that actually changed.

The SDK also sends the hashes it already has on each request, and the render service omits those mesh blobs from the response. This keeps the per-render network payload small even for scenes with hundreds of parts. Re-use a single <CadbuildrProvider> at the page level so this cache is shared across all your viewers.

Discretization — the one thing you control

The single biggest hit-rate predictor is parameter discretization. The SDK’s parameter form snaps sliders to your declared step, and the render cache keys on the resulting quantized value. If you ship a slider as Float("size", step=0.001), every visitor’s nudge lands on a distinct value and misses the cache. Pick the smallest step that produces visually distinct geometry — usually 0.1 or 1.0 for millimeters.

Common hit-rate killers, in order:

  1. Slider step too small (effectively continuous float values).
  2. A parameter with high cardinality but low visual impact (e.g. a free-picker Color that should be a small Enum over named choices).

Observing cache behaviour

The onRender callback on <CadbuildrViewer> fires on every successful render with metadata you can log or send to your own analytics — mesh hashes, byte sizes, and kernel render time:

<CadbuildrViewer
  dag={dag}
  onRender={(meta) => console.info("rendered", meta)}
/>

A render that resolves quickly and returns few mesh blobs (most omitted because you already hold their hashes) is a cache-friendly one. If renders are consistently slow with full payloads, revisit your slider steps and parameter cardinality above.