Composer is the foundation of every Magento 2 project, yet most deployment workflows treat it as an afterthought. Here's how to do it right — from local development to production deployment.
Always commit composer.lock
This is non-negotiable. The lockfile pins every dependency to an exact version, including transitive dependencies. Without it:
-
composer installon your CI server might install different versions than your local machine - A third-party package releases a breaking change and your next deploy breaks
- Security patches get installed automatically (sometimes good, sometimes unexpected)
# Always commit this
git add composer.lock
# Never add this to .gitignore
The composer.lock is your reproducibility guarantee.
Separate require from require-dev
Production servers should never install development dependencies (PHPUnit, PHPStan, Rector, etc.). They add weight and introduce unnecessary attack surface.
{
"require": {
"magento/product-community-edition": "~2.4.7",
"bettermagento/suite": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^11.0",
"phpstan/phpstan": "^1.10",
"rector/rector": "^1.0"
}
}
In your deployment:
# Production
composer install --no-dev --optimize-autoloader --no-interaction
# Local / CI
composer install
The --optimize-autoloader flag generates a class map instead of relying on PSR-4 file scanning — measurably faster in production.
Private package repositories
For proprietary modules (like BetterMagento), you need a private Composer repository. Options:
Option 1: Private Packagist
The easiest. Mirror public packages + host private ones. Expensive but worth it for teams.
Option 2: Satis
Self-hosted, open source. Generate a static JSON repository from your private packages:
composer create-project composer/satis --stability=dev
{
"name": "My Private Repo",
"homepage": "https://packages.example.com",
"repositories": [
{ "type": "vcs", "url": "git@github.com:yourorg/private-module.git" }
],
"require-all": true
}
Option 3: path repositories for local development
When developing a module locally alongside your Magento install:
{
"repositories": [
{
"type": "path",
"url": "../bettermagento/module-query-optimizer",
"options": {
"symlink": true
}
}
]
}
Composer symlinks the local directory — changes are reflected immediately without re-installing.
The Magento Composer plugin
Magento uses magento/composer-dependency-version-audit-plugin and magento/composer-root-update-plugin. These handle:
- Routing modules to
app/code/vsvendor/ - Managing
app/etc/configuration during updates - Version constraint auditing
Keep these plugins updated alongside Magento upgrades. Mismatched plugin versions are a common source of confusing upgrade failures.
Deployment workflow
A robust Magento deployment with Composer:
#!/bin/bash
set -e
# 1. Pull latest code
git pull origin main
# 2. Install dependencies (no dev, optimized autoloader)
composer install --no-dev --optimize-autoloader --no-interaction
# 3. Compile DI
php bin/magento setup:di:compile
# 4. Deploy static content
php bin/magento setup:static-content:deploy -f en_US
# 5. Run database upgrades
php bin/magento setup:upgrade --keep-generated
# 6. Flush caches
php bin/magento cache:flush
# 7. Warm critical pages
curl -s https://your-store.com/ > /dev/null
curl -s https://your-store.com/catalog/category/view/id/2 > /dev/null
The --keep-generated flag on setup:upgrade skips regenerating compiled code — use it in production when you've already run setup:di:compile.
Security: audit your dependencies
# Check for known vulnerabilities
composer audit
# Update all packages to latest compatible versions
composer update --with-all-dependencies
# Check for outdated packages
composer outdated
Set up automated security scanning in your CI pipeline. GitHub Actions example:
- name: Composer security audit
run: composer audit --format=json --no-dev
Fail the build on critical vulnerabilities, warn on high.
Managing Magento updates
When a new Magento patch or minor release drops:
# 1. Check what will change
composer require magento/product-community-edition:~2.4.8 --dry-run
# 2. Apply the update
composer require magento/product-community-edition:~2.4.8
# 3. Review changed files in vendor/
git diff composer.lock | grep "^+" | grep '"version"'
# 4. Run the full upgrade process
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy -f
Never run composer update without specifying packages on a production Magento install — it can update hundreds of packages at once, making rollbacks impossible to diagnose.
Quick reference
| Command | When to use |
|---|---|
composer install --no-dev --optimize-autoloader |
Every production deploy |
composer install |
Local development, CI |
composer require vendor/package |
Add a new dependency |
composer update vendor/package |
Update one package specifically |
composer audit |
Weekly security check |
composer outdated |
Before planning upgrades |
Get these habits right and your Magento deployments become predictable, reproducible, and secure.
Originally published on magevanta.com
Top comments (0)