Your amazing API doesn't matter if it's not in production. Deployment is where theory meets reality.
This chapter is short but important. We cover:
- CI/CD: Automated testing on every push
- Deployment: Getting code from your laptop to the internet
- Monitoring: Knowing when things break
- Scaling: Handling growth
These are the unglamorous but essential parts of shipping software.
If you're using Laravel Herd or Docker locally, you're already 80% of the way to production. The jump from local to production is just deployment configuration.
CI/CD Pipeline
The moment you push code, it should be automatically tested. The moment tests pass, it should deploy. No manual steps. No "I forgot to run tests."
# .github/workflows/test-and-deploy.yml
name: Test & Deploy
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:8.0
env:
MYSQL_DATABASE: test_db
MYSQL_ROOT_PASSWORD: secret
redis:
image: redis:7-alpine
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.4
extensions: mysql, redis
- name: Install Dependencies
run: composer install
- name: Copy .env.example to .env.test
run: cp .env.example .env.test
- name: Generate Key
run: php artisan key:generate --env=testing
- name: Run Tests
run: php artisan test
- name: Upload Coverage
uses: codecov/codecov-action@v3
CI/CD removes friction. Tests run automatically. Humans don't have to remember. The system enforces quality.
Simple Deployment
You don't need a complicated deployment process. Start simple:
#!/bin/bash
# deploy.sh
# Pull latest code
git pull origin main
# Install/update dependencies
composer install --no-dev
# Run migrations
php artisan migrate --force
# Clear caches
php artisan optimize
# Restart queue workers
php artisan queue:restart
# Done!
echo "Deployment complete"
Push to main → tests run → if passing, deploy. That's it.
Monitoring in Production
You can't fix what you don't see. Deploy monitoring with your app:
Route::get('/health', function () {
return [
'status' => 'ok',
'database' => DB::connection()->getPdo() ? 'ok' : 'down',
'cache' => Cache::get('test') !== null ? 'ok' : 'down',
'queue' => Queue::size() < 1000 ? 'ok' : 'warning',
];
});
Point your monitoring tool at /health. If it's not ok, alert your team.
Chapter 13 Summary
Deployment is not magic. It's just:
- Push code
- Run tests
- If tests pass, deploy
- Monitor to catch issues
- Rollback if needed
Start simple. Automate what you can. Monitor everything. Scale when needed, not before.