Xdebug is not something switched on for a request. Loading the extension replaces the engine’s function-call handlers for the lifetime of the process, so the overhead is paid on every call in every request — with the profiler off, remote debugging off, and every other setting left at its default.
; what a production php.ini usually has, and thinks is free
zend_extension = /usr/lib/php5/20100525/xdebug.so
xdebug.remote_enable = 0
xdebug.profiler_enable = 0
xdebug.default_enable = 1 ; stack traces on every notice — on by default
; the only configuration that costs nothing is the absent one:
; rm /etc/php5/fpm/conf.d/20-xdebug.ini
; service php5-fpm restart
; php -m | grep -i xdebug # expect no output at all
On an application making a lot of small function calls, the difference between loaded and absent is commonly somewhere between 1.5× and 3× on wall time — and it is invisible in application metrics because everything is uniformly slower. xdebug.default_enable is the specific default worth knowing about: it is on, and it means every notice and warning builds a formatted stack trace, so a codebase with a steady trickle of undefined-index notices is doing real work for output nobody reads. Xdebug also disables the OPcache optimiser when both are loaded, which compounds the cost with the loss of something already paid for. Keep it in a separate ini file included only on the development boxes, and check with php -m after any deploy that touches packages, because a distribution upgrade will happily put it back.