Magento best practices
Magento 2 (Adobe Commerce) is resource-intensive, placing high demands on memory, CPU, and I/O. A fast, stable storefront depends on the right caching layers, a working cron, and production mode. TurboStack provisions most of this for you; this page covers what is already configured and what to optimize on top.
What TurboStack configures for you
Set the app type to magento2 and the platform prepares the host for a Magento store:
- Document root - the vhost serves from the Magento
pub/directory inside your app root (/var/www/<user>/public_html), with a Magento-specific Nginx configuration (50main.conf). - Magento-aware Varnish - when Varnish is enabled, the platform installs a Magento-aware VCL on the host (
/etc/varnish/conf.d/50_main.vcl), so the full-page cache understands the storefront. - Log rotation - everything under the app's
var/log/is rotated weekly via logrotate so disks do not fill up. - Database tuning - a Magento-specific MySQL setting (
restrict_fk_on_non_standard_key = OFF) is applied for compatibility, and OPcache is enabled in the PHP runtime.
Enable what the store needs alongside it: MySQL, Redis, a search engine (Magento requires Elasticsearch or OpenSearch), and Varnish on the application.
Important
TurboStack does not edit the store's own configuration. Point Magento at Redis, at the search
engine and at Varnish yourself, and set up its cron. See
Recommended optimizations
Combine Magento's vendor guidance with the TurboStack options below. Most are one toggle away on the host's Services tab.
- Run in production mode - set the deploy mode to
productionfor live stores:bin/magento deploy:mode:set production. This compiles dependency injection (DI) and pre-generates static assets. After deploying code or configuration changes, run the standard sequencesetup:upgrade->setup:di:compile->setup:static-content:deploy->cache:flush(usesetup:upgrade --keep-generatedon production to preserve already-compiled code). - Enable Varnish full-page cache - this reduces time-to-first-byte significantly for storefront pages; keep it on for production.
- Use Redis for sessions and cache - do not use file sessions on a busy store. See
Redis cache tuning for theenv.phpblock and its lifetime settings. - Keep Elasticsearch/OpenSearch healthy - it is required; size it for your catalog (see below).
- Enable OPcache (and consider the realpath cache) in the PHP runtime to cut PHP parsing overhead.
- Optimize assets and images - minify/merge JS and CSS, use WebP/optimized images, and serve
pub/staticandpub/mediavia a Content Delivery Network (CDN) when possible. - Use an HTTP cache / CDN in front - offload static and media delivery. If a CDN fronts the site, TurboStack can disable Varnish caching of static/media to avoid double caching.
- Keep cron running - reindexing, price rules, emails, and message-queue consumers all depend on cron; never disable it on a live store.
- Run message-queue consumers as services - on a busy store, run consumers as persistent
systemd --userservices rather than relying only on cron, so they restart on failure. SeeMessage-queue consumers below.
Redis cache tuning
Magento reads its Redis connections from app/etc/env.php. TurboStack runs the two Redis instances;
the store has to be pointed at them.
Below is a complete app/etc/env.php for a Magento store on TurboStack. The Redis part is the block
between the //START and //END markers; everything around it is an ordinary Magento file, shown
so you can see where the block belongs.
<?php
return [
'backend' => [
'frontName' => 'admin'
],
'crypt' => [
'key' => '<your-encryption-key>'
],
'db' => [
'table_prefix' => 'md_',
'connection' => [
'default' => [
'host' => 'localhost',
'dbname' => '<dbname>',
'username' => '<dbuser>',
'password' => '<dbpassword>',
'active' => '1'
]
]
],
'resource' => [
'default_setup' => [
'connection' => 'default'
]
],
'x-frame-options' => 'SAMEORIGIN',
'MAGE_MODE' => 'production',
//START
'session' => [
'save' => 'redis',
'redis' => [
'host' => '/var/run/redis-persistent/redis.sock',
'port' => '0',
'password' => '',
'timeout' => '3',
'persistent_identifier' => '',
'database' => '1',
'compression_threshold' => '2048', // Set 0 to disable
'log_level' => '2',
'max_concurrency' => '50',
'break_after_frontend' => '5',
'break_after_adminhtml' => '30',
'first_lifetime' => '600',
'bot_first_lifetime' => '60',
'bot_lifetime' => '7200',
'disable_locking' => '0',
'min_lifetime' => '60',
'max_lifetime' => '2592000'
]
],
'cache' =>[
'frontend' => [
'default' => [
'id_prefix' => '104_',
'backend' => 'Magento\\Framework\\Cache\\Backend\\Redis',
'backend_options' => [
'server' => '/var/run/redis/redis.sock',
'port' => '0',
'persistent' => 'db2',
'database' => '2',
'password' => '',
'force_standalone' => '0',
'connect_retries' => '2',
'read_timeout' => '3',
'automatic_cleaning_factor' => '0',
'compress_threshold' => '2048',
// 'compress_data' => '1', // Let Magento pick best value, default 1
// 'compress_tags' => '1', // Let Magento pick best value, default 1
// 'compression_lib' => 'gzip', // Let Magento pick best value , prefer lz4 or snappy
'preload_keys' => [
'104_EAV_ENTITY_TYPES',
'104_GLOBAL_PLUGIN_LIST',
'104_DB_IS_UP_TO_DATE',
'104_SYSTEM_DEFAULT',
],
]
],
'page_cache' => [
'id_prefix' => '104_',
'backend' => 'Magento\\Framework\\Cache\\Backend\\Redis',
'backend_options' => [
'server' => '/var/run/redis/redis.sock',
'port' => '0',
'persistent' => 'db3',
'database' => '3',
'password' => '',
'force_standalone' => '0',
'connect_retries' => '2',
'read_timeout' => '3',
'compress_threshold' => '2048',
// 'compress_data' => '1', // Let Magento pick best value, default 1
// 'compress_tags' => '1', // Let Magento pick best value, default 1
// 'compression_lib' => 'gzip', // Let Magento pick best value , prefer lz4 or snappy
]
]
]
],
//END
'cache_types' => [
'config' => 1,
'layout' => 1,
'block_html' => 1,
'collections' => 1,
'reflection' => 1,
'db_ddl' => 1,
'eav' => 1,
'customer_notification' => 1,
'config_integration' => 1,
'config_integration_api' => 1,
'full_page' => 1,
'config_webservice' => 1,
'translate' => 1,
'compiled_config' => 1
],
'install' => [
'date' => 'Thu, 27 Sep 2018 18:41:40 +0000'
]
];
Warning
crypt/key and the database credentials above are placeholders. Magento generates the encryption
key during installation and uses it to decrypt stored credentials, so copy the key from your own
env.php and never from an example. A store that reuses someone else's key is not protected.
-
Sessions on the persistent instance, caches on the cache instance.
sessionpoints at/var/run/redis-persistent/redis.sock, both caches at/var/run/redis/redis.sock. See Sessions and cache for why they are split. -
portis0because the connection goes over the socket, not over a network port. The socket path is inhostfor sessions and inserverfor the caches. -
Each one gets its own database:
1for sessions on the persistent instance,2for the default cache and3for the full-page cache. Clearing one then does not touch the others. -
id_prefixmust match thepreload_keysentries. Both are104_here. Use your own prefix in both places, so keys stay unique when several sites share the instance. -
The compression options are commented out on purpose. Magento picks its own values;
lz4orsnappyare preferred overgzipif you do setcompression_lib.
After changing env.php, flush the cache:
php bin/magento cache:flush
If caching was not enabled before, turn it on so Redis is actually used:
php bin/magento cache:enable
Warning
Run every command on this page over SSH as the application's own
system user, from ~/public_html. Never run them as root: the files Magento writes would end up
owned by root, and PHP-FPM, which runs as your system user, can no longer read or write them.
Varnish settings
Magento 2 has built-in support for Varnish. Run these as your system user from ~/public_html, to
point it at the Varnish TurboStack runs:
bin/magento setup:config:set -n --http-cache-hosts=127.0.0.1:6081
magerun2 config:set system/full_page_cache/caching_application 2
magerun2 config:set system/full_page_cache/ttl 86400
magerun2 config:set system/full_page_cache/varnish/access_list 127.0.0.1,localhost
magerun2 config:set system/full_page_cache/varnish/backend_host 127.0.0.1
magerun2 config:set system/full_page_cache/varnish/backend_port 8080
- Varnish listens on port
6081, and the web server behind it on8080. caching_application 2selects Varnish instead of Magento's built-in full-page cache.ttlis the default Time to Live (TTL) in seconds.
Switch Varnish on per application with varnish_enabled, under Configure application >
Technologies. There is no host service to enable first. See
Configure Varnish.
Message-queue consumers
Magento offloads asynchronous work - reindexing, transactional emails, and order or coupon processing - to message queues handled by consumer processes. On a busy store, run each consumer as a persistent systemd --user service so it restarts on failure, instead of relying on cron alone.
Create a reusable template unit at ~/.config/systemd/user/magento-consumer@.service:
[Unit]
Description=Magento Consumer (%i)
After=network-online.target
Requires=dbus.socket
StartLimitIntervalSec=0
[Service]
Type=simple
WorkingDirectory=%h/public_html
ExecStart=php %h/public_html/bin/magento queue:consumers:start %I --single-thread --max-messages=10000
RestartSec=10s
Restart=always
[Install]
WantedBy=default.target
%iis the consumer name, so one template serves every queue, and%his your home directory.--single-threadruns one thread per process;--max-messages=10000restarts the consumer periodically to keep memory in check.
List the available consumers with php bin/magento queue:consumers:list, then enable and start one service per consumer (the name after @ is the consumer):
systemctl --user enable --now magento-consumer@sales.rule.update.coupon.usage.service
systemctl --user status magento-consumer@product_action_attribute.update.service
To drain queues faster on a busy store, run several consumers in parallel (more instances, or more of the same consumer). Keep the total number of consumers within the host's processor budget: never more than the core count, and keep a margin. Too many will slow the whole store. See Scale throughput with more instances.
For the systemd --user basics - including loginctl enable-linger so the services keep running after you log out - see How to manage user system services.
Sizing and scaling
TurboStack auto-tunes resource limits from the host's size, so start with the defaults. Override the tuning variables only when you have measured evidence (slow queries, cache evictions, search latency):
See Performance tuning before changing any of these. When a single host can no longer keep up, scale up the host before splitting services.
Stability
- Back up regularly - verify scheduled Backups cover both the database and the
pub/media,app/etc, andvardirectories. - Watch Health - monitor CPU, memory, and disk. Magento's
var/and media directories grow over time. - Keep versions current - track Magento/Adobe Commerce security patches and the PHP, MySQL, and Elasticsearch versions you run.
- Test on a staging clone - always trial upgrades, extensions, and theme changes on a copy before publishing to production.
Related
- Deploy Magento
- Magento reference
- How to run multiple Magento store views
- Troubleshooting Magento
- How to manage user system services
- Services
- Performance tuning