freddyliu From my understanding everything in the render function needs to be completed within a block otherwise there would be underruns and the block would be dropped.
That's correct.
Since process_fft() is called within the render function in the example
Right, in that example that may well be the case. However, if you jump forward to the following lecture, you'll see that the function is moved to a different thread.
You can use as a reference the example Audio/FFT-phase-vocoder that comes with the IDE. There, process_fft() is called via process_fft_background() in a separate task, created in setup() with gFFTTask = Bela_createAuxiliaryTask(&process_fft_background, 90, "fft-calculation")). This task is then scheduled (set to execute) at the appropriate moment from within render() via Bela_scheduleAuxiliaryTask(gFFTTask);