Skip to content
Decision 1 · Implementation + staging receipt

Budget for the whole container, not the program

The fallback order, the assembler as built, and the receipt from the test run: 215 MB of process memory against a 7.23 GB container peak.

Quoted verbatim from HYVIRAL’s specifications, code and logs. Internal paths and identifiers are redacted.

The decision

The assembler that joins rendered chunks into one MP4 understands the file format, and its output file still grows with the video’s size. Writing to disk stayed as the fallback; a fragmented MP4 would have needed its own compatibility decision.

From the source

Ruling on output storage. Candidates (i), (ii) and (iii) are bounded temporary storage, disk-backed execution and fragmented MP4:

  1. Output storage (D3): prove candidate (i) first, fall to (ii) the disk-backed Batch/Compute finalizer if (i) fails, and consider (iii) fMP4 only if both fail.

Implementation record, 9 October. Its early size estimate predates the measured run below:

As built for step 1 (9 October): candidate (i) without the VBV rate cap. moov-relocate.ts is the sequential writer (ported from the step-0 prototype, with stco → co64 promotion and a cascade unit test, failure-aware writes that reject on sink error/close); render-finalize.ts refuses a join whose estimated output (estimateFinalizeOutputBytes over the VERIFIED chunk sizes: video + PCM re-encoded at 192 kbit/s + 64 MiB moov allowance) exceeds FINALIZE_OUTPUT_BUDGET_BYTES = 24 GB before ffmpeg starts, writes the plain join to tmpfs, fingerprints it (finalize_media_fingerprint, per-stream -f md5), then relocates straight into createWriteStream({ resumable: true, preconditionOpts: { ifGenerationMatch: 0 } }) and checks outputBytes === plainBytes + (moovBytes − moovBytesIn) against the uploaded object's size. Memory is sampled independently (task-sampler.ts: RSS, tmpfs, cgroup memory.peak). The VBV cap on capture is deferred to the step-3 plan: a 90-minute join is ≈ 4.3 GB against a 24 GB budget, so the guard alone bounds step 1; the cap becomes necessary only when the ceiling admits footage whose unbounded output could exceed the budget, and it is a quality decision the owner should see measured first.

Synthetic staging finalizer receipt. Internal identifiers are redacted:

{"msg": "finalize_task_complete", "renderId": "[REDACTED: render ID]", "chunks": 45, "durationInFrames": 162000, "frameCheck": "passed", "concatMs": 503722, "streamed": true, "bytesServed": 7868435639, "rangeRequests": 135, "plainBytes": 6894189496, "outputBytes": 6894189496, "relocateMs": 102965, "uploadMs": 102965, "moovGrowthBytes": 0, "peakRssMb": 215, "peakTmpMb": 6575, "peakTmpDirs": ["[REDACTED: temporary directory]=6575"], "cgroupPeakBytes": 7234232320, "durationMs": 626638, "_ts": "2026-10-10T00:01:45.460092Z", "_sev": "INFO"}

The run, 9–10 October:

MeasureResult
Video duration90 minutes / 162,000 frames
Delivered object size reported by finalizer6.894 GB
Finalize task duration626.638 seconds
Reported peak process RSS215 MB
Container cgroup peak, including temporary storage7.234 GB
Output admission guard24 GB

GB is decimal; MB follows the sampler’s convention.

What this shows

The fallback order, a working one-file path, and a resource profile in which the memory the process reported was 3% of the container peak. The output guard bounds the file, not total container memory. Cleanup removed this large artifact before the full post-upload playback check ran, so that check remains for the next run.

Back to the case All code & records