Composer resolves dependencies, which needs memory and network access - both of which are limited on shared hosting. It also downloads code straight onto a production server, which is not where you want to discover that a package has changed.
The better shape
Resolve dependencies where you have the resources, and ship the result. The server then never runs Composer at all.
# on your machine or in CI
composer install --no-dev --optimize-autoloader --classmap-authoritative
rsync -az --delete vendor/ user@server:/var/www/site/vendor/
- --no-dev - test frameworks and debuggers are not on production.
- --optimize-autoloader - a class map instead of filesystem lookups, and a measurable speed-up.
- --classmap-authoritative - no fallback stat calls at all. Use it only when nothing generates classes at runtime.
If you must run it on the server
php -d memory_limit=-1 /usr/local/bin/composer install --no-dev --optimize-autoloader
The memory limit is the usual blocker. Raising it just for that command avoids raising it for the whole site.
Commit the lock file, never the vendor directory
composer.lock belongs in git - it is what makes two installs identical. The vendor directory does not: it makes the repository enormous and merges impossible.
Deploy without a broken window
Copying files into a live directory means some requests see half of the new code. Build into a new directory and switch a symlink, so the change is atomic.
ln -sfn /var/www/releases/2026-09-05 /var/www/current
sudo systemctl reload php8.3-fpm # clear the opcache of the old paths
Reload PHP-FPM after a deploy or opcache will keep serving the previous code from memory - see what opcache caches.