Streamline your Laravel deployment process with strategies for CI/CD pipelines, zero-downtime deploys, environment configuration, and DevOps tooling.
A polished Laravel app deserves a polished deployment pipeline. Whether you’re solo or scaling, DevOps practices help you deploy faster, safer, and with confidence.
Why Deployment Is Part of Engineering Quality
Deployments are where good codebases get hurt. The goal is not “deploy faster”. It is deploy safely, predictably, and with a rollback plan.
This post now adds rationale around why each step exists, so it is not just a list of commands.
Design Rationale and Trade-offs
Atomic deploys reduce panic
The symlink release pattern (or tools like Envoyer) work because they separate build time from run time. Your app switches to a new release instantly, and rollback is a pointer change.
Caching is a deployment concern
config:cache, route:cache, view:cache, and event:cache are valuable, but they can also break deployments if you run them at the wrong time or ship stale config. Make them part of a repeatable pipeline.
Migrations should be backwards compatible
Zero downtime deployments often fail because a migration changes a column before old code stops querying it. If you need true zero downtime, plan migrations in safe phases.
Operational Additions
- Add a
/upor/healthcheck route to validate the new release - Restart queue workers on deploy so they load the new code
- Monitor failed jobs and slow queues (Horizon helps)
- Keep secrets out of Git, and rotate keys when staff change
Fact Checks and Clarifications
- Laravel encourages running optimisations as part of deployment. Treat that as part of your release checklist, not something done ad hoc.
FAQ
Do I need Forge or Envoyer?
No, but they reduce human error. If you deploy often, tooling is worth it.
What breaks deploys most often?
Migrations that are not backwards compatible, and caches built with stale environment variables.
Should I deploy on Fridays?
Only if you have monitoring, rollback, and confidence in your process.
Key Takeaways
- Deployments are a system, not a button.
- Use atomic releases and plan rollback.
- Treat caching and migrations as first-class parts of the pipeline.
Environments & Configuration
Use .env for sensitive and dynamic config. Never commit .env to Git. Define environment-specific .env.production and .env.staging files.
In config/*.php, use:
'api_key' => env('API_KEY'),
Cache configs for performance:
php artisan config:cache
Zero-Downtime Deployment
Use Laravel Envoyer or a custom script for atomic deploys.
Alternative: manual symlink strategy:
/releases/current -> /releases/20250626_123456
Use php artisan down with --secret for access:
php artisan down --secret="super-secret-code"
Then deploy, then:
php artisan up
Deploy with Laravel Forge
- Provision server
- Connect repo (GitHub/Bitbucket)
- Configure deployments
- Add environment variables
- Queue monitoring with Horizon
Custom Deployment with Envoy
composer require laravel/envoy --dev
Create Envoy.blade.php:
@servers(['prod' => 'user@yourserver'])
@task('deploy', ['on' => 'prod'])
cd /var/www/app
git pull origin main
composer install --no-dev
php artisan migrate --force
php artisan config:cache
php artisan queue:restart
@endtask
Run:
vendor/bin/envoy run deploy
CI/CD Pipelines
Use GitHub Actions / GitLab CI / Bitbucket Pipelines:
Example .github/workflows/deploy.yml:
name: Deploy Laravel
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
- run: composer install --no-dev --optimize-autoloader
- run: php artisan config:cache
- run: php artisan route:cache
- run: curl -X POST https://forge.laravel.com/servers/.../deploy
Health Checks & Rollbacks
- Use
/healthroute for uptime monitors (e.g. Oh Dear, Pingdom) - Keep previous releases ready for rollback
- Use Supervisor to auto-restart failed queue workers
Real-World Application
In the jewellery ecommerce project, we:
- Used Forge + Horizon
- Deployed via GitHub Actions
- Achieved <10s rollback time
- Added deployment Slack notifications via Webhooks
Best Practices
- Automate what’s repeatable
- Use queues and horizon monitoring
- Document
.envvariable expectations - Use
php artisan config:cache,route:cache,view:cache - Validate deploys with post-deploy health check
Related Posts
Looking for Laravel support? I help businesses across Chester and the North West build and maintain Laravel applications. Learn more about my Laravel services or get in touch.