Raise the upload ceiling to a true 1 MB, and guard the fallback decoder against hanging #7

Closed
opened 2026-09-11 23:23:48 +00:00 by iec-admin · 0 comments
Contributor

Follow-up to #3 and #5.

1. The ceiling was more conservative than it needed to be

The upload budget was set to 900 KB on the assumption that multipart overhead needed meaningful headroom under the 1 MB ingress cap. Measured against production, the real envelope is about 200 bytes:

Body Result
1,048,576 B (exactly 1 MB) 413
1,048,300 B 401 — passed the ingress
1,047,000 B 401
1,044,000 B 401

So 148 KB of usable room was being left on the table. The budget is now derived as MAX_REQUEST_BYTES - 2048 (1,046,528 bytes — an order of magnitude more margin than measured, enough for any realistic filename), which reads as "1.0 MB" to the user.

Effect: videos up to ~1 MB now upload instead of being rejected at 0.9 MB, and photos retain slightly more resolution because the compressor has more room — the worst-case test image went from 1404×1053 to 1497×1122.

2. The fallback decoder could hang forever

decode() falls back to an <img> load when createImageBitmap throws. That promise settled only on onload or onerror; a load that did neither would leave the uploader stuck on Preparing… with nothing to time it out. Bounded at 20s now, which surfaces as a normal upload error instead of an indefinite spinner.

Still not fixed by this

A large hero video (the 12 MB ballantyne-hero-london-full.mp4) remains impossible to upload. 1 MB is the hard ingress ceiling and video cannot be re-encoded in the browser. The only real fix is raising nginx.ingress.kubernetes.io/proxy-body-size on the ingress.

Follow-up to #3 and #5. ## 1. The ceiling was more conservative than it needed to be The upload budget was set to 900 KB on the assumption that multipart overhead needed meaningful headroom under the 1 MB ingress cap. Measured against production, the real envelope is about **200 bytes**: | Body | Result | |---|---| | 1,048,576 B (exactly 1 MB) | `413` | | 1,048,300 B | `401` — passed the ingress | | 1,047,000 B | `401` | | 1,044,000 B | `401` | So 148 KB of usable room was being left on the table. The budget is now derived as `MAX_REQUEST_BYTES - 2048` (**1,046,528 bytes** — an order of magnitude more margin than measured, enough for any realistic filename), which reads as "1.0 MB" to the user. Effect: videos up to ~1 MB now upload instead of being rejected at 0.9 MB, and photos retain slightly more resolution because the compressor has more room — the worst-case test image went from 1404×1053 to 1497×1122. ## 2. The fallback decoder could hang forever `decode()` falls back to an `<img>` load when `createImageBitmap` throws. That promise settled only on `onload` or `onerror`; a load that did neither would leave the uploader stuck on `Preparing…` with nothing to time it out. Bounded at 20s now, which surfaces as a normal upload error instead of an indefinite spinner. ## Still not fixed by this A large hero video (the 12 MB `ballantyne-hero-london-full.mp4`) remains impossible to upload. 1 MB is the hard ingress ceiling and video cannot be re-encoded in the browser. The only real fix is raising `nginx.ingress.kubernetes.io/proxy-body-size` on the ingress.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
martin/ballantyne-www#7
No description provided.