Use this checklist to verify that your Symfony application is configured correctly for a production environment.
OPcache caches your code as compiled bytecode, so PHP doesn't have to
reinterpret it on every request. It ships with PHP by default since 8.5; on older versions the extension sometimes has to
be installed first. Check the following values, for example through phpinfo() or in php.ini (see
Runtime Configuration for all options):
OPcache is enabled (opcache.enable = 1)
OPcache preloading is enabled (opcache.preload holds the full path to Symfony's config/preload.php)
Preloading compiles the listed files once at server startup and keeps them in shared memory for every worker, so the framework's core classes never have to be loaded from disk per request.
opcache.preload_user is set to the web server user (usually www-data)
opcache.memory_consumption is 256 or higher
opcache.max_accelerated_files is 32531 or higher
OPcache is not checking PHP files for changes on every request (opcache.validate_timestamps = 0)
With timestamp validation off, OPcache skips a filesystem stat() on every cached file per request. The tradeoff is
that it no longer notices changed files, so the cache has to be cleared on each deployment (see Deployment below).
PHP resolves relative file paths to absolute ones and caches the result in the realpath cache. Check that it is sized generously:
realpath_cache_size is 4096K or higherrealpath_cache_ttl is 600 seconds (10 minutes) or longerThe Xdebug extension is absent or disabled in production
Xdebug hooks into the engine and slows down every request, even when no debugging session is active.
Check the following values, usually in config/:
framework.enabled_locales (usually in config/packages/translation.yaml) lists only the locales the application
actually uses.container.dumper.inline_factories: true set as a parameter in config/services.yamlIf Doctrine ORM is used, also check the following, usually in config/packages/doctrine.yaml (see also
Caching Drivers):
doctrine.dbal.server_version (or the serverVersion parameter in the DATABASE_URL environment variable) set to the
database version running in production
Without it, DBAL runs a query to detect the version on the first connection of every request. Setting it also lets Doctrine pick the right SQL dialect for your database.
The query cache
is configured (doctrine.orm.query_cache_driver)
The result cache
is configured (doctrine.orm.result_cache_driver)
Check the application's build and deployment process (see also Performance):
The application uses an optimized class map (composer dump-autoload --no-dev --classmap-authoritative)
An authoritative class map lets the autoloader resolve every class from a precomputed array, so it never falls back to searching the filesystem (and won't look for a class that isn't there).
OPcache is cleared after every deployment (for example by restarting the web server), so it picks up the changed files
Needed because production OPcache runs with validate_timestamps = 0, so it won't notice the new files on its own.
composer audit)The web server user (usually www-data) can only read the application's source files, not modify them
The public directory contains no files with sensitive information (such as a .env)
The load balancer / proxy IP addresses are configured through the SYMFONY_TRUSTED_PROXIES environment variable or
framework.trusted_proxies (usually in config/packages/framework.yaml)
Only relevant behind a load balancer or reverse proxy (such as an ingress controller in Kubernetes). Without it,
Symfony treats the proxy as the client and ignores the X-Forwarded-* headers, so the client IP, scheme and host are
wrong. See How to Configure Symfony to Work behind a Load Balancer or a Reverse Proxy.
Custom error pages are set for HTTP status codes such as 404, 403 and 500 (usually in
templates/bundles/TwigBundle/Exception/)
The default Symfony error page looks broken to visitors. A custom template keeps the experience on-brand even when something goes wrong (see How to Customize Error Pages).
A custom favicon is set
robots.txt file in the public directory