Assets & caching
Before a render, the SDK uploads your scene's files (its assets). Each file is identified by a hash of its content, so a file that has not changed is never uploaded twice.
You do not call anything for this. render(), renderVideo() and bake()
upload what is missing and skip the rest.
First render Uploaded: 148 MB
Camera moves Uploaded: 2 KB
Texture change Uploaded: 6 MBShow upload progress
await bakery3.render({
onUpload: ({ cached, uploaded, bytesUploaded, bytesTotal }) => {
setStatus(`${uploaded} uploading, ${cached} already cached`);
setProgress(bytesTotal ? bytesUploaded / bytesTotal : 1);
},
});
// onUpload receives:
// { cached: 3, uploaded: 1, bytesUploaded: 6291456, bytesTotal: 6291456 }cached and uploaded count files. When nothing has changed, bytesTotal is
0.
What causes a new upload
The scene is exported to a .glb on every render. If the export is different
from last time, it is uploaded again. Moving a mesh, hiding a variant or
swapping a material all change it.
Moving only the camera does not. The camera is sent with the render request, not
inside the .glb, so an orbit uploads almost nothing.
What gets uploaded
| Kind | What it is |
|---|---|
scene | The exported .glb: geometry, materials, hierarchy, embedded textures. |
texture | Textures used by a node material, which the .glb does not carry. |
hdri | An environment map of your own. A preset one is not uploaded. |
geometry | Standalone geometry. |
animation | Per-frame motion for a video. |
ies | An IES light profile. |
When an upload fails
The SDK tries each file three times. If it still fails, the render throws
AssetUploadIncomplete:
Bakery3Error: Could not upload scene.glb (148.2 MB): 403 Forbidden
Why: The presigned upload URL was rejected. These expire, and they
are signed over an exact set of headers.
Fix: Retry the render. If it keeps failing, check for a service
worker or proxy that rewrites request headers.Files go straight from the browser to storage on a signed URL. If the error keeps coming back, the usual cause is a service worker or a corporate proxy that adds, drops or rewrites a request header.
The same render twice comes from the cache
If you ask for a render that was already made in the same project (same scene, camera, size and quality), you get the existing image back. It is not rendered again, and it costs nothing. This works for as long as the first image is stored, which is the project's retention: 30 days by default.
When we update the renderer, the cache starts fresh, because the image could come out different.
Stop a retry from rendering twice
Pass an idempotencyKey. A second call with the same key returns the first
render instead of starting a new one, so your own retry button cannot charge
twice.
await bakery3.render({ idempotencyKey: `sku-${sku}-hero-v3` });See Render image for more.
Delete your uploaded files
Delete one file by its hash, or every file in the project. Call it from your server, because it needs your secret key.
import { Bakery3Server } from '@oeave/bakery3/node';
const bakery3 = new Bakery3Server(process.env.BAKERY3_SECRET_KEY!);
await bakery3.assets.delete('sha256:9f2b…');
// { hash: 'sha256:9f2b…', deleted: true }
await bakery3.assets.deleteAll();
// { deleted: 240 }Delete uploaded files on a project in Settings deletes every file too, and the REST API has a route for each. The next render uploads what it needs again. A render still waiting in the queue for a file you deleted can fail, and a failed render costs nothing.
Privacy and retention
Results are private by default and served from signed URLs that expire. Your files are kept under your own project. A file no render has used for the project's retention window (never less than two days) is deleted on its own. See Limits for the numbers.
