A 118-Minute Mix Ate 9.3 GB of RAM: What It Taught Me About Decoding Audio
A post-mortem from my music service: one 118-minute mix took a worker to 9.3 GB, and the decoding rules that came out of it, with the numbers from 3,141 tracks.

The night a mix took down the demo
On 2026-10-08 at 13:12 UTC my signal engine reached a 118-minute Drive mix and decoded it whole. One worker reached 9.3 GB. The engine shares a 31 GB box with k3s, which leaves it about 8 GB, so the OOM killer took the worker and the portfolio demo pod next to it. k3s restarted the demo within seconds, with no image loss. The engine needed a rule.
The post-mortem in 40 seconds

config/config.yml, the signal section (excerpt)
signal:
sample_rate: 22050
n_fft: 2048
hop_length: 512
excerpt_policy: "middle"
excerpt_seconds: 60
max_decode_minutes: 10 # longer files are decoded as one centred window of this lengthThe rule: decode at most 10 minutes
A file longer than max_decode_minutes is decoded as one window of that length centred on the middle, by ffmpeg with -ss and -t, so nothing else of the file is ever held in memory. The analysis excerpt (the middle 60 s) lands inside that window, and its offset stays relative to the file. The record says what happened, word for word: long file: 117.8 min; decoded the middle 10.0 min (offset 3234 s); dynamics and loudness measured on that window. The same 7,068.8 s mix now analyses in 27.0 s. 17 tracks in the catalogue take this path.
The fix

Two decoders, one output
libsndfile reads mp3 and FLAC natively and is the fast path (2,827 tracks). It cannot read AAC in m4a, which is what every upload is, so those go through ffmpeg as raw float32 (297 tracks). Both produce the same thing: float32 at the rate asked for, plus what the file said about itself. Resampling happens once, at decode, with soxr, so no analyzer ever resamples again. The files arrive at 44,100 Hz (2,149) or 48,000 Hz (992), all stereo; the analysis signal is mono at 22,050 Hz.
What decoding found in 3,141 tracks

What decoding found
- 2,364 of 3,141 tracks decode to samples above full scale. The decoder does not clip them, so the engine does not either; it logs the overshoot.
- 1,356 had a DC offset removed before analysis, because an offset shifts RMS and fools the zero-crossing rate.
- 5 FLACs failed with
read_timestamp() failed in the middleuntil the decoder learned to retry with an output-side seek. - When a worker dies, the whole process pool breaks and cannot say which file did it. The batch rebuilds the pool, retries at full width, then runs the tail one worker at a time, so only the culprit is dead-lettered as
WORKER_CRASHED, retryable.
The trade-off
The cap bounds memory, but the loudness of a two-hour mix is now the loudness of its middle 10 minutes. That is a product decision, so it lives in the record's warnings instead of in someone's memory.
Part 2 of 14, next: How Shazam Sees a Song: The Spectrogram Behind My Music AI.
Part 2 of 14, next: How Shazam Sees a Song: The Spectrogram Behind My Music AI.
More: LinkedIn · Instagram. Portfolio and case studies: designsbyduhart.org.
If any of this saved you an afternoon, Buy me a coffee.