Laravel Mastery: Deployment & DevOps

11 minute read Laravel Mastery · Part 8

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 /up or /health check 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 /health route 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 .env variable expectations
  • Use php artisan config:cache, route:cache, view:cache
  • Validate deploys with post-deploy health check

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.