ob_flush sends an application-initiated buffer. There may be multiple nested
ob_start()‘s in any PHP script.
ob_flush passes the current content to the upper layer.
PHP itself might (at its own discretion) buffer output. This depends on the back-end. But usually
FastCGI has a socket buffer on its own. Therefore
flush() needs to be invoked as well to send the current content to the web server.
And now the web server might itself implement another buffering scheme (
mod_deflate or content filter), which you have no influence over. But this is seldom, as it needs to be configured specifically.
Anyway, use both.