"It worked fine on my machine." It is the most frustrating sentence in software development, and in Laravel, it usually appears right after a production deployment.
When a site works perfectly on a local environment like Herd, Valet, or Sail but breaks in production, it is rarely a bug in your core PHP logic. It is almost always a gap between how local servers and production Linux environments behave. Here is the systematic workflow I use to isolate and fix production-only failures.
1. Check the Log Streams First
Before blindly tweaking configurations, inspect the application and web server logs.
- Laravel Logs: Check storage/logs/laravel.log. If it is not updating, you likely have a file permissions issue.
- Web Server Logs: Check /var/log/nginx/error.log or Apache's error logs to catch 500 internal errors occurring before Laravel bootstraps.
2. Config Caching and env() Traps
The single most common cause of missing variables in production is env() calls outside configuration files. When you run php artisan config:cache, Laravel stops reading the .env file entirely and relies solely on the generated config cache. If you use env('MY_KEY') directly inside controllers, jobs, or views, it will return null in production.
- Fix: Define all environment variables inside config/*.php files and use config('services.my_key') throughout your application. Always refresh the cache after updates using php artisan config:cache.
3. Storage and Cache File Permissions
Local environments usually run under your personal user account with open permissions, but production servers execute under web users like www-data or nginx. If Laravel cannot write to storage or bootstrap directories, you will hit HTTP 500 errors or silent log failures.
- Ensure the web server owns the directories and set correct file modes:
- Bash
4. Missing Storage Symlinks and APP_URL Misconfigurations
Uploaded assets like user avatars working locally but returning 404s in production usually point to two culprits:
- Missing Symlink: The public/storage directory link is missing on the server. Run php artisan storage:link.
- Incorrect APP_URL: If APP_URL in .env is still set to http://localhost, asset paths, signed URLs, and mail links will break in production. Update APP_URL to your full domain scheme (e.g., [https://example.com](https://example.com)).
5. Case-Sensitive File Systems
Local macOS and Windows file systems are case-insensitive, while Linux is strictly case-sensitive. A view reference like view('Users.Profile') or an image path like logo.PNG will load seamlessly locally but throw a View [Users.Profile] not found exception on Linux. Match your file names and controller references letter-for-letter.
6. Stale Queue Workers
When running background queues via Supervisor or Systemd, queue processes hold the application code in memory. If you deploy new code without restarting the workers, they continue executing the old code. Add php artisan queue:restart to your deployment script every time you ship.
Following this sequence turns a stressful production incident into a systematic, fast check.



