Case 01 / Clinical imaging / 2026
The measurement that isn’t allowed to be wrong
A multi-tenant viewer for orthodontic DICOM and photogrammetry volumes. 31.2 MB per study, a browser tab, and one rule: no number the system can’t stand behind.
01 / The constraint
Every thumbnail asked for the whole volume.
Clinical reviewers need to look at a 3D volume plane by plane. The volume is one C-ordered float32 array: 256 × 256 × 125, about 31.2 MB. The viewer loads a strip of thumbnails before the reviewer touches anything.
The storage layer had just stopped being a local directory. Every one of those thumbnails asked for the whole object. On a laptop that's a file read. Over a bucket it's a network transfer, repeated, on the hot path. The request path saturated and the API started returning 504s.
02 / The call
The planes are contiguous. Ask for one.
In a C-ordered (nz, ny, nx) array, plane k starts at
k × nx × ny × 4 and runs for nx × ny × 4 bytes. One plane is
256 KB. So the API stopped downloading volumes.
Storage.get_range(ref, offset, length) seeks on a local file and sends an
S3 Range header on a bucket. The viewer asks for one plane at a time.
- Range request
- 256 KB
- Offset
- 15.75 MB
- Whole object
- 31.25 MB
Verified byte-identical to the whole-array slice on the real volume. That's 99.2% less transferred per request, and it removes the 504s because the hot path no longer contains a 31 MB transfer.
A short range raises 416 instead of returning fewer bytes. Returning a
short plane would reshape into a wrong-sized image and draw the wrong anatomy. A
failed request is better than a plausible wrong one.
03 / The invariant
A number is a claim about the world.
Photogrammetry poses can be solved without a verified scale. A viewer that ignores
that will happily measure a jaw in millimetres that mean nothing. The API exposes
scale.verified. When it's false, the measurement is withheld.
The value is absent from the payload, so there's nothing for a client to render by mistake. A test pins the rule, and that test is why you can trust the toggle above.
04 / What broke
Three things that cost real time.
The first range implementation returned fewer bytes.
bytes[start:start+length] is silently short at the end of an object.
The shorter buffer reshaped into a wrong-sized plane. Fixed by raising 416.
Four suppress(...) blocks swallowed storage errors.
A bucket outage made jobs look fine in memory while never persisting, with nothing
in any log. Suppressed failures are logged now.
The dev object store is apps/api/.data.
Deleting it wipes every uploaded source. It's not obvious, and it costs an
afternoon the first time.
05 / Evidence
What's measured, and what isn't.
| Claim | Method | State |
|---|---|---|
| 31.25 MB whole object | 256 × 256 × 125 × 4 bytes | ● measured |
| 256 KB per plane | nx × ny × 4 bytes | ● measured |
| 99.2% less transferred | Byte-compared against the whole-array slice | ● measured |
| 416 on a short range | Regression test | ● measured |
| 168 API and invariant tests | Suite run | ● measured |
| Real segmentation over a real CT | The pipeline is deployed; the model hasn't been run over a study | ○ unverified |
The last row stays on the page because the rule applies to this site too. The plumbing isn't the result.