Какие production-риски чаще всего возникают в проектах на PHP: производительность, зависимости, конкурентность, деплой или observability?
Главные production-риски PHP: отсутствие OPcache/JIT (производительность), широкие Composer constraints без аудита CVE (зависимости), race conditions в транзакциях и проблемы с Swoole/FrankenPHP (конкурентность), non-atomic деплой без symlink-swap (деплой), отсутствие structured logging и трейсинга (observability).
Производительность
PHP share-nothing архитектура означает, что каждый запрос загружает весь код заново. Основные узкие места: отсутствие OPcache, N+1 запросы в Eloquent/Doctrine, синхронные curl-вызовы к внешним API. Решения: включить opcache.enable=1, opcache.jit=1255 (PHP 8+), использовать Redis/Memcached для кэширования, переносить тяжёлые операции в очереди (Laravel Queue, RabbitMQ).
Зависимости и supply chain
Composer-зависимости с широкими version constraints (^1.0) могут автоматически обновиться до версии с CVE. Риски: устаревший symfony/http-foundation, guzzlehttp/guzzle с открытыми уязвимостями. Практика: фиксировать composer.lock в VCS, запускать composer audit в CI, использовать roave/security-advisories как dev-зависимость.
# Проверка уязвимостей в зависимостях
composer audit
# Запрет установки пакетов с CVE через meta-пакет
composer require --dev roave/security-advisories:dev-latest
Конкурентность
Классический PHP-FPM однопоточен на уровне запроса — нет shared state между воркерами, но есть race conditions при работе с файлами и БД. Проблемы: double-spend при параллельных транзакциях без SELECT FOR UPDATE, file-based сессии без локов на высокой нагрузке. При переходе на Swoole/RoadRunner/FrankenPHP появляются настоящие concurrency-проблемы: статические переменные и Singleton-паттерны становятся global state между запросами.
Деплой
Основные риски: деплой в production прямо на живой директории (no atomic swap), прогон миграций до деплоя нового кода (backward compatibility), отсутствие health checks. Правильный подход: symlink-деплой (Deployer, Capistrano), запуск php artisan migrate --force только для backward-compatible миграций, использование feature flags для destructive changes.
# Деплой через Deployer (атомарное переключение symlink)
dep deploy production
# Проверка синтаксиса перед деплоем
find . -name '*.php' -exec php -l {} \; | grep -v 'No syntax errors'
Observability
PHP-приложения часто деплоятся без структурированного логирования и трейсинга. Критично: настроить Monolog с JSON-форматером и centralized logging (ELK/Loki), добавить Sentry или Bugsnag для exception tracking, интегрировать OpenTelemetry для distributed tracing (особенно при микросервисной архитектуре).
Подводные камни
- OPcache кэширует скомпилированный байткод, но при деплое без
opcache_reset()или symlink-swap старый код может обслуживать запросы ещё несколько минут. - Swoole и FrankenPHP несовместимы с кодом, использующим статические переменные как request-scoped storage — нужен полный аудит синглтонов.
- Composer
autoload_classmapне обновляется автоматически при добавлении новых классов безcomposer dump-autoload. - PHP max_execution_time по умолчанию 30 секунд — долгие задачи (CSV import, отчёты) падают в production без предупреждения.
- memory_limit по умолчанию 128M — обработка больших файлов или изображений с GD/Imagick вызывает fatal error без graceful degradation.
- Отсутствие liveness/readiness probe в Kubernetes: FPM может принимать запросы, но бесконечно ждать БД при старте.
- file_get_contents/curl без timeout — одна медленная внешняя зависимость блокирует воркер FPM, исчерпывая пул при небольшой нагрузке.
What hurts your answer
- Говорить только о запуске PHP, но не об эксплуатации
- Не упоминать observability, обновления, безопасность и rollback
- Описывать риски абстрактно, без способов их снижать
What they're listening for
- Видит production-риски PHP
- Говорит про monitoring, rollout, rollback и безопасность
- Умеет ранжировать риски по вероятности и влиянию