APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com LOG_CHANNEL=stack
LOG_LEVEL=warning DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=your_app
DB_USERNAME=your_user
DB_PASSWORD=strong_random_password CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com LOG_CHANNEL=stack
LOG_LEVEL=warning DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=your_app
DB_USERNAME=your_user
DB_PASSWORD=strong_random_password CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com LOG_CHANNEL=stack
LOG_LEVEL=warning DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=your_app
DB_USERNAME=your_user
DB_PASSWORD=strong_random_password CACHE_STORE=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
npm run build
npm run build
npm run build
composer install --no-dev --optimize-autoloader
npm ci && npm run build
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
php artisan queue:restart
composer install --no-dev --optimize-autoloader
npm ci && npm run build
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
php artisan queue:restart
composer install --no-dev --optimize-autoloader
npm ci && npm run build
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
php artisan queue:restart
php artisan migrate --force
php artisan migrate --force
php artisan migrate --force
Queue: default,notifications,emails
Processes: 3
Queue: default,notifications,emails
Processes: 3
Queue: default,notifications,emails
Processes: 3
Worker 1: payments (1 process, high priority)
Worker 2: default,notifications (3 processes)
Worker 3: exports,reports (2 processes, can be slow)
Worker 1: payments (1 process, high priority)
Worker 2: default,notifications (3 processes)
Worker 3: exports,reports (2 processes, can be slow)
Worker 1: payments (1 process, high priority)
Worker 2: default,notifications (3 processes)
Worker 3: exports,reports (2 processes, can be slow) - APP_DEBUG=false prevents stack traces from leaking to users. Leaving this true in production is a security vulnerability.
- LOG_LEVEL=warning prevents your log files from filling the disk with debug information.
- Use Redis (or Valkey, which is Redis-compatible) for cache, sessions, and queues in production. The file and database drivers don't scale. - Hetzner offers the best price-to-performance ratio for CPU and RAM. Ideal for budget-conscious deployments.
- DigitalOcean provides a polished experience with predictable pricing. Strong ecosystem of add-ons.
- Vultr offers competitive pricing with good global coverage.
- Linode (now Akamai) provides solid performance with straightforward pricing.
- AWS gives maximum flexibility and the broadest service catalog, but with higher complexity and cost. - Nginx (configured for your chosen Octane driver or PHP-FPM)
- PHP 8.4 with essential extensions
- MySQL, MariaDB, or PostgreSQL
- Valkey for caching and queues
- Node.js and npm for asset compilation
- Supervisor for queue workers and daemons
- UFW firewall with sensible defaults - A new release directory is created
- Your repository is cloned or updated
- Composer dependencies are installed
- npm dependencies are installed and assets are built
- Your deploy script runs (migrations, cache clearing, etc.)
- The symlink switches from the old release to the new one
- PHP-FPM/Octane workers are reloaded - Hourly backups for applications with high write volume
- Daily backups for most applications
- Store backups in a different region than your primary server
- Test restoring from backups periodically — an untested backup is not a backup - Enable the slow query log to identify performance problems
- Set innodb_buffer_pool_size to 60-80% of available RAM on a dedicated database server
- Use connection pooling if your application creates many short-lived connections
- Monitor query performance through Deploynix's server metrics and Laravel Pulse - CPU usage: Sustained high CPU indicates resource contention or runaway processes
- Memory usage: Track consumption trends to predict when you need to scale
- Disk usage: Running out of disk space causes cascading failures
- Network I/O: Unusual spikes might indicate a DDoS attack or a deployment pulling large dependencies - CPU above 90% for more than 10 minutes
- Memory above 85%
- Disk usage above 80% - Laravel Pulse for production performance trends, slow queries, and queue throughput
- Laravel Telescope (filtered) for capturing exceptions and failed jobs in production
- Custom health check endpoints that verify database, cache, queue, and external API connectivity - Database access from specific IP addresses (if you connect remotely)
- Application-specific ports (WebSockets on port 6001, etc.)
- Blocking known bad IP ranges - Keep PHP, Nginx, MySQL, and all system packages updated
- Run composer audit regularly to check for vulnerable dependencies
- Use Sanctum for API authentication with granular token scopes
- Implement rate limiting on authentication and API endpoints
- Store sensitive values in environment variables, never in code - Separate your database onto a dedicated server. This is usually the first scaling step and provides the biggest impact.
- Separate your cache (Valkey) onto a dedicated server. This prevents cache eviction during application memory pressure.
- Add worker servers for queue processing. This keeps background jobs from competing with web requests for CPU.
- Add web servers behind a load balancer. Deploynix's load balancer supports round robin, least connections, and IP hash methods. - Sessions stored in Redis/Valkey (not file)
- Cache in Redis/Valkey (not file)
- File uploads on external storage (S3, not local disk)
- Queues using Redis/Valkey (not the database or sync driver)
- No local file writes that other servers need to access - [ ] APP_DEBUG=false and APP_ENV=production are set
- [ ] Database credentials use a strong, unique password
- [ ] Session, cache, and queue drivers are set to Redis/Valkey
- [ ] SSL certificate is provisioned
- [ ] Firewall rules are configured
- [ ] Backup schedule is configured and tested
- [ ] Health monitoring is enabled
- [ ] Queue workers are configured and running - [ ] Tests pass before deployment
- [ ] Migrations are tested against a copy of production data
- [ ] Assets are compiled for production
- [ ] Config, route, view, and event caches are refreshed
- [ ] Queue workers are restarted to pick up new code
- [ ] Deployment is verified by checking the application's health endpoint - [ ] Application responds correctly to key user flows
- [ ] Queue workers are processing jobs
- [ ] No new errors appearing in logs
- [ ] Server metrics (CPU, memory, disk) are within normal ranges
- [ ] Scheduled tasks are running as expected